From 35fc9697cc539644056d5cd13a3faefde0b5fc4e Mon Sep 17 00:00:00 2001 From: Steven Kirbach Date: Mon, 12 Nov 2018 11:16:08 -0800 Subject: [PATCH 1/2] initial commit of system.xaml --- .gitignore | 12 +- Directory.Build.props | 13 + Directory.Build.targets | 2 + HelloWorld.sln | 25 - HelloWorld/HelloWorld.csproj | 9 - Microsoft.Dotnet.Wpf.sln | 37 + Packaging.targets | 26 + Publishing.targets | 3 + SystemResources.props | 24 + Test.cmd | 3 + Tests.sln | 121 + eng/Version.Details.xml | 4 +- eng/Versions.props | 13 +- eng/build.yml | 12 +- .../templates/phases/publish-build-assets.yml | 13 +- eng/common/templates/steps/helix-publish.yml | 2 +- global.json | 5 +- src/Directory.Build.Props | 4 + .../Directory.Build.Props | 4 + .../src/Common/src/System/SR.cs | 91 + .../src/Directory.Build.Props | 10 + .../Shared/MS/Internal/CriticalExceptions.cs | 69 + .../Internal/FriendAccessAllowedAttribute.cs | 49 + .../Shared/MS/Internal/SafeSecurityHelper.cs | 530 ++ .../MS/Internal/SecurityCriticalDataForSet.cs | 94 + .../Internal/Xaml/Context/XamlContextStack.cs | 160 + .../MS/Internal/Xaml/Context/XamlFrame.cs | 59 + .../Xaml/Parser/SpecialBracketCharacters.cs | 139 + .../src/Shared/MS/Utility/BindUriHelper.cs | 187 + .../src/Shared/MS/Utility/FrugalList.cs | 2344 ++++++ .../src/Shared/MS/Utility/FrugalMap.cs | 2184 +++++ .../src/Shared/MS/Utility/ItemList.cs | 194 + .../src/Shared/MS/Utility/ItemMap.cs | 149 + .../src/Shared/MS/Utility/Maps.cs | 118 + .../src/Shared/MS/Utility/PerfService.cs | 78 + .../src/Shared/MS/Utility/Trace.cs | 169 + .../src/Shared/MS/Utility/TraceProvider.cs | 645 ++ .../src/Shared/MS/Win32/ExternDll.cs | 51 + .../src/Shared/MS/Win32/HandleCollector.cs | 184 + .../src/Shared/MS/Win32/HwndSubclass.cs | 742 ++ .../src/Shared/MS/Win32/HwndWrapper.cs | 505 ++ .../src/Shared/MS/Win32/HwndWrapperHook.cs | 26 + .../src/Shared/MS/Win32/LoadLibraryHelper.cs | 117 + .../Shared/MS/Win32/ManagedWndProcTracker.cs | 315 + .../Shared/MS/Win32/MessageOnlyHwndWrapper.cs | 21 + .../src/Shared/MS/Win32/NativeMethodsCLR.cs | 7309 +++++++++++++++++ .../src/Shared/MS/Win32/NativeMethodsOther.cs | 1793 ++++ .../MS/Win32/NativeMethodsSetLastError.cs | 176 + .../Shared/MS/Win32/SafeNativeMethodsCLR.cs | 681 ++ .../Shared/MS/Win32/SafeNativeMethodsOther.cs | 345 + .../src/Shared/MS/Win32/SafeSystemMetrics.cs | 159 + .../Shared/MS/Win32/UnsafeNativeMethodsCLR.cs | 4236 ++++++++++ .../MS/Win32/UnsafeNativeMethodsCompiler.cs | 60 + .../MS/Win32/UnsafeNativeMethodsEventTrace.cs | 261 + .../MS/Win32/UnsafeNativeMethodsOther.cs | 1632 ++++ .../Win32/UnsafeNativeMethodsTextServices.cs | 3820 +++++++++ .../src/Shared/MS/Win32/WinInet.cs | 56 + .../src/Shared/RefAssemblyAttrs.cs | 78 + .../src/Shared/System/Windows/Ink/KnownIds.cs | 324 + .../System/Windows/InterOp/OSVersionHelper.cs | 332 + .../Windows/InterOp/OperatingSystemVersion.cs | 52 + .../System/Windows/Markup/ReflectionHelper.cs | 723 ++ .../Markup/Replacements/TypeUriConverter.cs | 133 + .../RuntimeIdentifierPropertyAttribute.cs | 135 + .../Windows/Markup/TypeConverterHelper.cs | 496 ++ .../Windows/Markup/XmlCompatibilityReader.cs | 2065 +++++ .../Windows/Markup/XmlWrappingReader.cs | 188 + .../Windows/Media/TypeConverterHelper.cs | 115 + src/Microsoft.DotNet.Wpf/src/System.Xaml.sln | 37 + .../src/System.Xaml/Configurations.props | 8 + .../src/System.Xaml/Directory.Build.Props | 9 + .../src/System.Xaml/FxCop/Xaml/CodeQuality.cs | 9 + .../System.Xaml/FxCop/Xaml/Globalization.cs | 9 + .../FxCop/Xaml/Microsoft.Design.cs | 5 + .../FxCop/Xaml/Microsoft.Naming.cs | 65 + .../System.Xaml/FxCop/Xaml/Microsoft.Usage.cs | 25 + .../src/System.Xaml/FxCop/Xaml/Performance.cs | 48 + .../src/System.Xaml/FxCop/Xaml/Reliability.cs | 12 + .../src/System.Xaml/FxCop/Xaml/Security.cs | 19 + .../src/System.Xaml/FxCop/Xaml/Stability.cs | 7 + .../Resources/ExceptionStringTable.txt | 417 + .../src/System.Xaml/Resources/Strings.resx | 1038 +++ .../src/System.Xaml/Resources/win32res.rc | 11 + .../src/System.Xaml/SR.cs | 21 + .../src/System.Xaml/System.Xaml.csproj | 104 + ...dMarkupExtensionExpressionTypeAttribute.cs | 20 + .../System/Windows/Markup/AmbientAttribute.cs | 18 + .../System/Windows/Markup/ArrayExtension.cs | 141 + .../Windows/Markup/BuildTopDownAttribute.cs | 24 + .../Markup/ConstructorArgumentAttribute.cs | 50 + .../Markup/ContentPropertyAttribute.cs | 56 + .../Windows/Markup/ContentWrapperAttribute.cs | 80 + .../Windows/Markup/DateTimeValueSerializer.cs | 173 + .../Windows/Markup/DependsOnAttribute.cs | 67 + .../Markup/DictionaryKeyPropertyAttribute.cs | 26 + .../Windows/Markup/IComponentConnector.cs | 36 + .../System/Windows/Markup/INameScope.cs | 40 + .../Windows/Markup/INameScopeDictionary.cs | 15 + .../Windows/Markup/IProvideValueTarget.cs | 37 + .../System/Windows/Markup/IQueryAmbient.cs | 15 + .../System/Windows/Markup/IUriContext.cs | 32 + .../Windows/Markup/IValueSerializerContext.cs | 44 + .../Windows/Markup/IXamlTypeResolver.cs | 37 + .../System/Windows/Markup/MarkupExtension.cs | 30 + ...rkupExtensionBracketCharactersAttribute.cs | 31 + .../MarkupExtensionReturnTypeAttribute.cs | 63 + .../System/Windows/Markup/MemberDefinition.cs | 15 + .../Markup/NameScopePropertyAttribute.cs | 36 + .../System/Windows/Markup/NullExtension.cs | 47 + .../Windows/Markup/PropertyDefinition.cs | 37 + .../Windows/Markup/RootNamespaceAttribute.cs | 46 + .../System/Windows/Markup/StaticExtension.cs | 209 + .../Markup/StaticExtensionConverter.cs | 54 + .../TrimSurroundingWhitespaceAttribute.cs | 34 + .../System/Windows/Markup/TypeExtension.cs | 157 + .../Windows/Markup/TypeExtensionConverter.cs | 55 + .../Windows/Markup/UidPropertyAttribute.cs | 60 + .../System/Windows/Markup/ValueSerializer.cs | 285 + .../Markup/ValueSerializerAttribute.cs | 20 + ...hitespaceSignificantCollectionAttribute.cs | 33 + .../Markup/XamlSetMarkupExtensionAttribute.cs | 21 + .../Markup/XamlSetMarkupExtensionEventArgs.cs | 51 + .../Markup/XamlSetTypeConverterAttribute.cs | 21 + .../Markup/XamlSetTypeConverterEventArgs.cs | 54 + .../Windows/Markup/XamlSetValueEventArgs.cs | 29 + .../Markup/XmlLangPropertyAttribute.cs | 60 + .../Markup/XmlnsCompatibleWithAttribute.cs | 87 + .../Markup/XmlnsDefinitionAttribute.cs | 125 + .../Windows/Markup/XmlnsPrefixAttribute.cs | 97 + .../System.Xaml/System/Windows/NameScope.cs | 390 + .../System/Windows/NameValidationHelper.cs | 61 + .../System/Xaml/AllowedMemberLocations.cs | 20 + .../System/Xaml/AttachableMemberIdentifier.cs | 82 + .../System/Xaml/AttachablePropertyServices.cs | 554 ++ .../System/Xaml/Context/ContextServices.cs | 55 + .../System/Xaml/Context/HashSet.cs | 28 + .../Xaml/Context/ICheckIfInitialized.cs | 14 + .../System/Xaml/Context/NameFixupGraph.cs | 502 ++ .../System/Xaml/Context/NameFixupToken.cs | 207 + .../Xaml/Context/ObjectWriterContext.cs | 1163 +++ .../System/Xaml/Context/ObjectWriterFrame.cs | 232 + .../System/Xaml/Context/SavedContext.cs | 41 + .../Xaml/Context/ServiceProviderContext.cs | 429 + .../System/Xaml/Context/XamlCommonFrame.cs | 97 + .../System/Xaml/Context/XamlContext.cs | 381 + .../Xaml/Context/XamlObjectWriterFactory.cs | 38 + .../System/Xaml/Context/XamlParserContext.cs | 314 + .../System/Xaml/Context/XamlParserFrame.cs | 44 + .../System.Xaml/System/Xaml/EventConverter.cs | 71 + .../Xaml/Events/ObjectCreatedEventArgs.cs | 25 + .../System/Xaml/Events/XamlObjectEventArgs.cs | 39 + .../System/Xaml/IAmbientProvider.cs | 42 + .../System/Xaml/IAttachedPropertyStore.cs | 34 + .../System/Xaml/IDestinationTypeProvider.cs | 13 + .../System/Xaml/INamespacePrefixLookup.cs | 15 + .../System/Xaml/IRootObjectProvider.cs | 15 + .../System.Xaml/System/Xaml/IXamlLineInfo.cs | 19 + .../System/Xaml/IXamlLineInfoConsumer.cs | 16 + .../System/Xaml/IXamlNameProvider.cs | 13 + .../System/Xaml/IXamlNameResolver.cs | 61 + .../System/Xaml/IXamlNamespaceResolver.cs | 16 + .../System/Xaml/IXamlObjectWriterFactory.cs | 19 + .../System/Xaml/IXamlSavedContextProvider.cs | 12 + .../System/Xaml/IXamlSchemaContextProvider.cs | 16 + .../System.Xaml/System/Xaml/IXamlTemplate.cs | 32 + .../Xaml/InfosetObjects/DeferredWriter.cs | 327 + .../InfosetObjects/ObjectWriterSettings.cs | 19 + .../System/Xaml/InfosetObjects/XamlNodes.cs | 274 + .../Xaml/InfosetObjects/XamlObjectWriter.cs | 2694 ++++++ .../XamlObjectWriterSettings.cs | 86 + .../Xaml/InfosetObjects/XamlReaderSettings.cs | 61 + .../Xaml/InfosetObjects/XamlTextReader.cs | 219 + .../InfosetObjects/XamlTextReaderSettings.cs | 56 + .../Xaml/InfosetObjects/XamlXmlReader.cs | 450 + .../InfosetObjects/XamlXmlReaderSettings.cs | 42 + .../System/Xaml/MS/Impl/ArrayHelper.cs | 41 + .../Xaml/MS/Impl/AssemblyNamespacePair.cs | 33 + .../Xaml/MS/Impl/ConcurrentDictionary.cs | 215 + .../System/Xaml/MS/Impl/KnownStrings.cs | 114 + .../MS/Impl/PositionalParameterDescriptor.cs | 22 + .../Xaml/MS/Impl/XamlDirectiveCollection.cs | 214 + .../Xaml/MS/Impl/XamlPropertyInfoKey.cs | 102 + .../System/Xaml/MS/Impl/XmlNsInfo.cs | 570 ++ .../System/Xaml/NameReferenceConverter.cs | 85 + .../System/Xaml/NameScopeDictionary.cs | 346 + .../System/Xaml/NamespaceDeclaration.cs | 39 + .../System/Xaml/ObjectReaderSettings.cs | 6 + .../Xaml/Parser/GenericTypeNameParser.cs | 339 + .../Xaml/Parser/GenericTypeNameScanner.cs | 385 + .../System/Xaml/Parser/MePullParser.cs | 514 ++ .../System/Xaml/Parser/MeScanner.cs | 638 ++ .../Xaml/Parser/NamespacePrefixLookup.cs | 38 + .../System/Xaml/Parser/NodeStreamSorter.cs | 717 ++ .../System/Xaml/Parser/ScannerNodeType.cs | 36 + .../System/Xaml/Parser/XamlAttribute.cs | 178 + .../System/Xaml/Parser/XamlName.cs | 100 + .../System/Xaml/Parser/XamlPropertyName.cs | 103 + .../System/Xaml/Parser/XamlPullParser.cs | 1199 +++ .../System/Xaml/Parser/XamlQualifiedName.cs | 102 + .../System/Xaml/Parser/XamlScanner.cs | 866 ++ .../System/Xaml/Parser/XamlScannerNode.cs | 46 + .../System/Xaml/Parser/XamlScannerStack.cs | 93 + .../System/Xaml/Parser/XamlText.cs | 369 + .../Xaml/Permissions/XamlAccessLevel.cs | 151 + .../Xaml/Permissions/XamlLoadPermission.cs | 340 + .../System/Xaml/Primitives/LineInfo.cs | 38 + .../Xaml/Primitives/ReaderBaseDelegate.cs | 112 + .../System/Xaml/Primitives/ReaderDelegate.cs | 57 + .../Primitives/ReaderMultiIndexDelegate.cs | 105 + .../System/Xaml/Primitives/WriterDelegate.cs | 134 + .../Xaml/Primitives/XamlBackgroundReader.cs | 338 + .../System/Xaml/Primitives/XamlNodeList.cs | 129 + .../System/Xaml/Primitives/XamlNodeQueue.cs | 108 + .../System/Xaml/Primitives/XamlSubreader.cs | 165 + .../Xaml/RefOnly/LooseTypeExtensions.cs | 144 + .../Xaml/Replacements/DateTimeConverter2.cs | 63 + .../Replacements/DateTimeOffsetConverter2.cs | 108 + .../DateTimeValueSerializerContext.cs | 62 + .../System/Xaml/Replacements/Reference.cs | 48 + .../Xaml/Replacements/TypeListConverter.cs | 54 + .../Xaml/Replacements/TypeTypeConverter.cs | 85 + .../System/Xaml/Runtime/ClrObjectRuntime.cs | 737 ++ .../Xaml/Runtime/DynamicMethodRuntime.cs | 746 ++ .../Runtime/PartialTrustTolerantRuntime.cs | 466 ++ .../Xaml/Runtime/XamlRuntimeSettings.cs | 13 +- .../Xaml/Schema/BuiltInValueConverter.cs | 344 + .../System/Xaml/Schema/ClrAttachableEvent.cs | 57 + .../Xaml/Schema/ClrAttachableProperty.cs | 98 + .../System/Xaml/Schema/ClrEvent.cs | 65 + .../Xaml/Schema/ClrNamespaceUriParser.cs | 93 + .../System/Xaml/Schema/ClrProperty.cs | 457 ++ .../System/Xaml/Schema/CollectionReflector.cs | 421 + .../System/Xaml/Schema/DirectiveProperty.cs | 150 + .../System/Xaml/Schema/ImplicitProperty.cs | 189 + .../System/Xaml/Schema/MemberReflector.cs | 341 + .../Xaml/Schema/ReferenceEqualityComparer.cs | 62 + .../System/Xaml/Schema/Reflector.cs | 512 ++ .../Xaml/Schema/SafeReflectionInvoker.cs | 401 + .../System/Xaml/Schema/TypeBits.cs | 103 + .../System/Xaml/Schema/TypeReflector.cs | 1171 +++ .../System/Xaml/Schema/UnknownProperty.cs | 190 + .../System/Xaml/Schema/XamlCollectionKind.cs | 16 + .../System/Xaml/Schema/XamlDirective.cs | 213 + .../System/Xaml/Schema/XamlMemberInvoker.cs | 240 + .../System/Xaml/Schema/XamlNamespace.cs | 312 + .../System/Xaml/Schema/XamlTypeInvoker.cs | 470 ++ .../System/Xaml/Schema/XamlValueConverter.cs | 163 + .../System/Xaml/Schema/XaslMember.cs | 392 + .../System/Xaml/Schema/XaslMemberReference.cs | 170 + .../System/Xaml/Schema/XaslNamespace.cs | 144 + .../System/Xaml/Schema/XmlNamespace.cs | 112 + .../src/System.Xaml/System/Xaml/XData.cs | 56 + .../System/Xaml/XamlDeferLoadAttribute.cs | 61 + .../System/Xaml/XamlDeferringLoader.cs | 16 + .../System.Xaml/System/Xaml/XamlException.cs | 286 + .../System.Xaml/System/Xaml/XamlLanguage.cs | 506 ++ .../System/Xaml/XamlMarkupExtensionWriter.cs | 629 ++ .../src/System.Xaml/System/Xaml/XamlMember.cs | 1124 +++ .../System/Xaml/XamlObjectReader.cs | 3366 ++++++++ .../System/Xaml/XamlObjectReaderSettings.cs | 11 + .../System.Xaml/System/Xaml/XamlProperty.cs | 71 + .../src/System.Xaml/System/Xaml/XamlReader.cs | 100 + .../System.Xaml/System/Xaml/XamlRuntime.cs | 87 + .../System/Xaml/XamlSchemaContext.cs | 1522 ++++ .../System/Xaml/XamlSchemaContextSettings.cs | 27 + .../System.Xaml/System/Xaml/XamlServices.cs | 233 + .../src/System.Xaml/System/Xaml/XamlType.cs | 1870 +++++ .../System.Xaml/System/Xaml/XamlTypeName.cs | 285 + .../System/Xaml/XamlTypeTypeConverter.cs | 112 + .../src/System.Xaml/System/Xaml/XamlWriter.cs | 91 + .../System/Xaml/XamlWriterSettings.cs | 17 + .../System.Xaml/System/Xaml/XamlXmlWriter.cs | 2210 +++++ .../System/Xaml/XamlXmlWriterSettings.cs | 25 + .../Internal/Markup/StringValueSerializer.cs | 46 + .../Markup/TypeConverterValueSerializer.cs | 55 + .../src/System.Xaml/otherassemblyattrs.cs | 17 + .../test/Common/TestServices/DrtBase.cs | 3152 +++++++ .../Common/TestServices/DrtBaseGlobalInput.cs | 58 + .../test/Common/TestServices/DrtBaseInput.cs | 638 ++ .../MS/Internal/MultiTargetUtilities.cs | 18 + .../TestServices/MS/Internal/PointUtil.cs | 242 + .../MS/Internal/SecurityCriticalDataForSet.cs | 94 + .../Common/TestServices/MS/Win32/ExternDll.cs | 65 + .../TestServices/MS/Win32/HandleCollector.cs | 184 + .../TestServices/MS/Win32/NativeMethodsCLR.cs | 7309 +++++++++++++++++ .../MS/Win32/NativeMethodsOther.cs | 1793 ++++ .../MS/Win32/NativeMethodsSetLastError.cs | 174 + .../MS/Win32/SafeNativeMethodsCLR.cs | 681 ++ .../MS/Win32/SafeNativeMethodsOther.cs | 345 + .../MS/Win32/UnsafeNativeMethodsCLR.cs | 4236 ++++++++++ .../MS/Win32/UnsafeNativeMethodsOther.cs | 1634 ++++ .../Common/TestServices/TestServices.csproj | 10 + .../test/Common/dir.props | 6 + .../test/CommonAssemblyInfo.cs | 3 + src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml.sln | 121 + .../BamlAvoidXmlTest/BamlAvoidXmlTest.cs | 84 + .../BamlAvoidXmlTest/BamlAvoidXmlTest.csproj | 17 + .../BamlTestClasses40/BCMarkupExtension.cs | 81 + .../BamlTestClasses40/BamlBindingPath.xaml | 16 + .../BamlTestClasses40/BamlBindingPath.xaml.cs | 14 + .../BamlTestClasses40.csproj | 19 + .../BracketCharacterAttribute.xaml | 50 + .../BracketCharacterAttribute.xaml.cs | 28 + .../BamlTestClasses40/DeferContMEPV.xaml | 26 + .../BamlTestClasses40/DeferContMEPV.xaml.cs | 12 + .../ResourceResDeferredDictionary.xaml | 92 + .../ResourceResDeferredDictionary.xaml.cs | 17 + .../ResourceResForwardRef1.xaml | 15 + .../ResourceResForwardRef1.xaml.cs | 17 + .../ResourceResForwardRef2.xaml | 44 + .../ResourceResForwardRef2.xaml.cs | 17 + .../BamlTestClasses40/ResourceResInsert.xaml | 48 + .../ResourceResInsert.xaml.cs | 23 + .../ResourceResOverwrite.xaml | 48 + .../ResourceResOverwrite.xaml.cs | 23 + .../BamlTestClasses40/TempDPSetOrder1.xaml | 29 + .../BamlTestClasses40/TempDPSetOrder1.xaml.cs | 58 + .../DrtXaml/BamlTestClasses40/WpfObfus1.xaml | 5 + .../BamlTestClasses40/WpfObfus1.xaml.cs | 12 + .../DrtXaml/BamlTestClasses40/XmlSpace1.xaml | 5 + .../BamlTestClasses40/XmlSpace1.xaml.cs | 12 + .../DrtXaml/BamlTestClasses40/XmlSpace2.xaml | 5 + .../BamlTestClasses40/XmlSpace2.xaml.cs | 12 + .../DrtXaml/BamlTestClasses40/XmlSpace3.xaml | 5 + .../BamlTestClasses40/XmlSpace3.xaml.cs | 12 + .../test/DRT/DrtXaml/DrtXaml/DrtTestFinder.cs | 76 + .../DRT/DrtXaml/DrtXaml/DrtXaml.Tests.csproj | 30 + .../test/DRT/DrtXaml/DrtXaml/DrtXamlBase.cs | 235 + .../DRT/DrtXaml/DrtXaml/ExtensionMethods.cs | 21 + .../DRT/DrtXaml/DrtXaml/NodeListValidator.cs | 93 + .../DrtXaml/Tests/AdvXamlFeatureTests.cs | 1470 ++++ .../Tests/AttachablePropertyServicesTests.cs | 854 ++ .../DrtXaml/Tests/AvoidSystemXmlTest.cs | 101 + .../DRT/DrtXaml/DrtXaml/Tests/BamlTests.cs | 141 + .../DrtXaml/DrtXaml/Tests/BasicXamlTests.cs | 928 +++ .../DrtXaml/DrtXaml/Tests/CollectionTests.cs | 271 + .../DRT/DrtXaml/DrtXaml/Tests/EventTests.cs | 67 + .../DrtXaml/Tests/FactoryArgumentTests.cs | 348 + .../DrtXaml/Tests/LoadPermissionTests.cs | 219 + .../DrtXaml/Tests/MarkupExtensionTests.cs | 335 + .../DrtXaml/Tests/NameReferenceTests.cs | 1057 +++ .../DrtXaml/DrtXaml/Tests/NodeStreamTests.cs | 823 ++ .../DrtXaml/Tests/ObjectReaderTests.cs | Bin 0 -> 233600 bytes .../DrtXaml/Tests/ObjectWriterBasicTests.cs | 1169 +++ .../DrtXaml/Tests/SavedContextTests.cs | 83 + .../DRT/DrtXaml/DrtXaml/Tests/SchemaTests.cs | 1996 +++++ .../DrtXaml/DrtXaml/Tests/SubreaderTests.cs | 257 + .../DrtXaml/Tests/TypeArgumentTests.cs | 209 + .../DrtXaml/Tests/ValueSerializerTests.cs | 311 + .../DrtXaml/DrtXaml/Tests/WpfUsageTests.cs | 823 ++ .../DrtXaml/Tests/Xaml/CdfTemplateTests.cs | 618 ++ .../DrtXaml/Tests/Xaml/XamlServicesTests.cs | 219 + .../Tests/XamlMarkupExtensionWriterTests.cs | 389 + .../DrtXaml/Tests/XamlTextWriterTests.cs | 1853 +++++ .../DrtXaml/Tests/XamlXmlReaderTests.cs | 77 + .../DrtXaml/XamlTestFrameWork/Assert.cs | 238 + .../DrtXaml/XamlTestFrameWork/Attributes.cs | 86 + .../XamlTestFrameWork/TestDelegates.cs | 11 + .../DrtXaml/XamlTestFrameWork/TestFinder.cs | 371 + .../XamlTestFrameWork/XamlTestInfoBlock.cs | 143 + .../FriendWithKey.cs | 11 + .../XamlTestClasses.FriendWithKey.csproj | 7 + .../FriendWithoutKey.cs | 11 + .../XamlTestClasses.FriendWithoutKey.csproj | 7 + .../test/DRT/DrtXaml/XamlTestClasses/AMEET.cs | 40 + .../XamlTestClasses/AmbientProperties.cs | 165 + .../DrtXaml/XamlTestClasses/ArrayHolder.cs | 12 + .../XamlTestClasses/AttachableProperties.cs | 173 + .../DRT/DrtXaml/XamlTestClasses/BamlTypes.cs | 29 + .../DrtXaml/XamlTestClasses/Collections.cs | 517 ++ .../XamlTestClasses/ConverterNameRefMath.cs | 665 ++ .../DRT/DrtXaml/XamlTestClasses/CpaClasses.cs | 64 + .../DestinationTypeConverterTypes.cs | 69 + .../DRT/DrtXaml/XamlTestClasses/DrtXaml.snk | Bin 0 -> 596 bytes .../XamlTestClasses/DummyCollections.cs | 917 +++ .../DRT/DrtXaml/XamlTestClasses/Elements.cs | 650 ++ .../XamlTestClasses/FactoryProvider.cs | 196 + .../DrtXaml/XamlTestClasses/IPVTClasses.cs | 80 + .../XamlTestClasses/InitializationClasses.cs | 387 + .../XamlTestClasses/MarkupExtensions.cs | 145 + .../test/DRT/DrtXaml/XamlTestClasses/NSGO.cs | 24 + .../DRT/DrtXaml/XamlTestClasses/NameScopes.cs | 39 + .../DRT/DrtXaml/XamlTestClasses/NodeStream.cs | 443 + .../XamlTestClasses/ObjectReaderClasses.cs | Bin 0 -> 147096 bytes .../XamlTestClasses/ObsoleteClasses.cs | 108 + .../XamlTestClasses/PropertyClasses.cs | 65 + .../XamlTestClasses/TemplateClasses.cs | 64 + .../DrtXaml/XamlTestClasses/TestExpression.cs | 46 + .../DrtXaml/XamlTestClasses/TestTemplate.cs | 101 + .../DrtXaml/XamlTestClasses/TypeConverters.cs | 402 + .../XamlTestClasses/ValueSerializerClasses.cs | 365 + .../Xaml/CdfTemplateClasses.cs | 728 ++ .../XamlMarkupExtensionWriterClasses.cs | 1120 +++ .../XamlObjectWriterClasses.cs | 14 + .../XamlTestClasses/XamlTestClasses.csproj | 17 + .../XamlTestClasses/XamlTextWriterClasses.cs | 96 + .../DrtXaml/XamlTestClasses/XmlDataHolder.cs | 43 + .../DrtXaml/XamlTestClasses/XmlNsClasses.cs | 18 + .../test/DRT/DrtXaml/dir.props | 6 + src/Microsoft.DotNet.Wpf/test/DRT/dir.props | 6 + .../test/Directory.Build.props | 13 + .../test/MultiTargeting.props | 65 + src/Microsoft.DotNet.Wpf/test/dir.props | 6 + 403 files changed, 125404 insertions(+), 64 deletions(-) delete mode 100644 HelloWorld.sln delete mode 100644 HelloWorld/HelloWorld.csproj create mode 100644 Microsoft.Dotnet.Wpf.sln create mode 100644 Packaging.targets create mode 100644 Publishing.targets create mode 100644 SystemResources.props create mode 100644 Test.cmd create mode 100644 Tests.sln create mode 100644 src/Directory.Build.Props create mode 100644 src/Microsoft.DotNet.Wpf/Directory.Build.Props create mode 100644 src/Microsoft.DotNet.Wpf/src/Common/src/System/SR.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Directory.Build.Props create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/CriticalExceptions.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/FriendAccessAllowedAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/SafeSecurityHelper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/SecurityCriticalDataForSet.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Context/XamlContextStack.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Context/XamlFrame.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Parser/SpecialBracketCharacters.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/BindUriHelper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalList.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalMap.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/ItemList.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/ItemMap.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/Maps.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/PerfService.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/Trace.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/TraceProvider.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/ExternDll.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HandleCollector.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndSubclass.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndWrapper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndWrapperHook.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/LoadLibraryHelper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/ManagedWndProcTracker.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/MessageOnlyHwndWrapper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsCLR.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsOther.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsSetLastError.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/SafeNativeMethodsCLR.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/SafeNativeMethodsOther.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/SafeSystemMetrics.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCLR.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCompiler.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsEventTrace.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsOther.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsTextServices.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/WinInet.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/RefAssemblyAttrs.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Ink/KnownIds.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/InterOp/OSVersionHelper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/InterOp/OperatingSystemVersion.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/ReflectionHelper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/Replacements/TypeUriConverter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/RuntimeIdentifierPropertyAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/TypeConverterHelper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/XmlCompatibilityReader.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/XmlWrappingReader.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Media/TypeConverterHelper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml.sln create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/Configurations.props create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/Directory.Build.Props create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/CodeQuality.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Globalization.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Microsoft.Design.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Microsoft.Naming.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Microsoft.Usage.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Performance.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Reliability.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Security.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Stability.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/Resources/ExceptionStringTable.txt create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/Resources/Strings.resx create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/Resources/win32res.rc create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/SR.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System.Xaml.csproj create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/AcceptedMarkupExtensionExpressionTypeAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/AmbientAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ArrayExtension.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/BuildTopDownAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ConstructorArgumentAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ContentPropertyAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ContentWrapperAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/DateTimeValueSerializer.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/DependsOnAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/DictionaryKeyPropertyAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IComponentConnector.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/INameScope.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/INameScopeDictionary.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IProvideValueTarget.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IQueryAmbient.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IUriContext.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IValueSerializerContext.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IXamlTypeResolver.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MarkupExtension.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MarkupExtensionBracketCharactersAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MarkupExtensionReturnTypeAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MemberDefinition.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/NameScopePropertyAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/NullExtension.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/PropertyDefinition.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/RootNamespaceAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/StaticExtension.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/StaticExtensionConverter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/TrimSurroundingWhitespaceAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/TypeExtension.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/TypeExtensionConverter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/UidPropertyAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ValueSerializer.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ValueSerializerAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/WhitespaceSignificantCollectionAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetMarkupExtensionAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetMarkupExtensionEventArgs.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetTypeConverterAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetTypeConverterEventArgs.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetValueEventArgs.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlLangPropertyAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlnsCompatibleWithAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlnsDefinitionAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlnsPrefixAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/NameScope.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/NameValidationHelper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/AllowedMemberLocations.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/AttachableMemberIdentifier.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/AttachablePropertyServices.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ContextServices.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/HashSet.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ICheckIfInitialized.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/NameFixupGraph.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/NameFixupToken.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ObjectWriterContext.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ObjectWriterFrame.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/SavedContext.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ServiceProviderContext.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlCommonFrame.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlContext.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlObjectWriterFactory.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlParserContext.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlParserFrame.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/EventConverter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Events/ObjectCreatedEventArgs.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Events/XamlObjectEventArgs.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IAmbientProvider.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IAttachedPropertyStore.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IDestinationTypeProvider.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/INamespacePrefixLookup.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IRootObjectProvider.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlLineInfo.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlLineInfoConsumer.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlNameProvider.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlNameResolver.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlNamespaceResolver.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlObjectWriterFactory.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlSavedContextProvider.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlSchemaContextProvider.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlTemplate.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/DeferredWriter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/ObjectWriterSettings.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlNodes.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlObjectWriter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlObjectWriterSettings.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlReaderSettings.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlTextReader.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlTextReaderSettings.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlXmlReader.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlXmlReaderSettings.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/ArrayHelper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/AssemblyNamespacePair.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/ConcurrentDictionary.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/KnownStrings.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/PositionalParameterDescriptor.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XamlDirectiveCollection.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XamlPropertyInfoKey.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XmlNsInfo.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/NameReferenceConverter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/NameScopeDictionary.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/NamespaceDeclaration.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/ObjectReaderSettings.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/GenericTypeNameParser.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/GenericTypeNameScanner.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/MePullParser.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/MeScanner.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/NamespacePrefixLookup.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/NodeStreamSorter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/ScannerNodeType.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlName.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlPropertyName.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlPullParser.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlQualifiedName.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlScanner.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlScannerNode.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlScannerStack.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlText.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Permissions/XamlAccessLevel.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Permissions/XamlLoadPermission.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Primitives/LineInfo.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Primitives/ReaderBaseDelegate.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Primitives/ReaderDelegate.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Primitives/ReaderMultiIndexDelegate.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Primitives/WriterDelegate.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Primitives/XamlBackgroundReader.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Primitives/XamlNodeList.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Primitives/XamlNodeQueue.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Primitives/XamlSubreader.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/RefOnly/LooseTypeExtensions.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Replacements/DateTimeConverter2.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Replacements/DateTimeOffsetConverter2.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Replacements/DateTimeValueSerializerContext.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Replacements/Reference.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Replacements/TypeListConverter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Replacements/TypeTypeConverter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Runtime/ClrObjectRuntime.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Runtime/DynamicMethodRuntime.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Runtime/PartialTrustTolerantRuntime.cs rename HelloWorld/Program.cs => src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Runtime/XamlRuntimeSettings.cs (53%) create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/BuiltInValueConverter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/ClrAttachableEvent.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/ClrAttachableProperty.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/ClrEvent.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/ClrNamespaceUriParser.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/ClrProperty.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/CollectionReflector.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/DirectiveProperty.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/ImplicitProperty.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/MemberReflector.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/ReferenceEqualityComparer.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/Reflector.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/SafeReflectionInvoker.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/TypeBits.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/TypeReflector.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/UnknownProperty.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XamlCollectionKind.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XamlDirective.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XamlMemberInvoker.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XamlNamespace.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XamlTypeInvoker.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XamlValueConverter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XaslMember.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XaslMemberReference.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XaslNamespace.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Schema/XmlNamespace.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XData.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlDeferLoadAttribute.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlDeferringLoader.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlException.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlLanguage.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlMarkupExtensionWriter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlMember.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlObjectReader.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlObjectReaderSettings.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlProperty.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlReader.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlRuntime.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlSchemaContext.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlSchemaContextSettings.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlServices.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlType.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlTypeName.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlTypeTypeConverter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlWriter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlWriterSettings.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlXmlWriter.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlXmlWriterSettings.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/ms/Internal/Markup/StringValueSerializer.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/ms/Internal/Markup/TypeConverterValueSerializer.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/System.Xaml/otherassemblyattrs.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/DrtBase.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/DrtBaseGlobalInput.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/DrtBaseInput.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/MS/Internal/MultiTargetUtilities.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/MS/Internal/PointUtil.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/MS/Internal/SecurityCriticalDataForSet.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/MS/Win32/ExternDll.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/MS/Win32/HandleCollector.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/MS/Win32/NativeMethodsCLR.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/MS/Win32/NativeMethodsOther.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/MS/Win32/NativeMethodsSetLastError.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/MS/Win32/SafeNativeMethodsCLR.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/MS/Win32/SafeNativeMethodsOther.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/MS/Win32/UnsafeNativeMethodsCLR.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/MS/Win32/UnsafeNativeMethodsOther.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/TestServices/TestServices.csproj create mode 100644 src/Microsoft.DotNet.Wpf/test/Common/dir.props create mode 100644 src/Microsoft.DotNet.Wpf/test/CommonAssemblyInfo.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml.sln create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlAvoidXmlTest/BamlAvoidXmlTest.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlAvoidXmlTest/BamlAvoidXmlTest.csproj create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/BCMarkupExtension.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/BamlBindingPath.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/BamlBindingPath.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/BamlTestClasses40.csproj create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/BracketCharacterAttribute.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/BracketCharacterAttribute.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/DeferContMEPV.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/DeferContMEPV.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/ResourceResDeferredDictionary.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/ResourceResDeferredDictionary.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/ResourceResForwardRef1.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/ResourceResForwardRef1.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/ResourceResForwardRef2.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/ResourceResForwardRef2.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/ResourceResInsert.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/ResourceResInsert.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/ResourceResOverwrite.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/ResourceResOverwrite.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/TempDPSetOrder1.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/TempDPSetOrder1.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/WpfObfus1.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/WpfObfus1.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/XmlSpace1.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/XmlSpace1.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/XmlSpace2.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/XmlSpace2.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/XmlSpace3.xaml create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/BamlTestClasses40/XmlSpace3.xaml.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/DrtTestFinder.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/DrtXaml.Tests.csproj create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/DrtXamlBase.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/ExtensionMethods.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/NodeListValidator.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/AdvXamlFeatureTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/AttachablePropertyServicesTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/AvoidSystemXmlTest.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/BamlTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/BasicXamlTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/CollectionTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/EventTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/FactoryArgumentTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/LoadPermissionTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/MarkupExtensionTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/NameReferenceTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/NodeStreamTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/ObjectReaderTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/ObjectWriterBasicTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/SavedContextTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/SchemaTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/SubreaderTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/TypeArgumentTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/ValueSerializerTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/WpfUsageTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/Xaml/CdfTemplateTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/Xaml/XamlServicesTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/XamlMarkupExtensionWriterTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/XamlTextWriterTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/Tests/XamlXmlReaderTests.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/XamlTestFrameWork/Assert.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/XamlTestFrameWork/Attributes.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/XamlTestFrameWork/TestDelegates.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/XamlTestFrameWork/TestFinder.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/DrtXaml/XamlTestFrameWork/XamlTestInfoBlock.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses.FriendWithKey/FriendWithKey.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses.FriendWithKey/XamlTestClasses.FriendWithKey.csproj create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses.FriendWithoutKey/FriendWithoutKey.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses.FriendWithoutKey/XamlTestClasses.FriendWithoutKey.csproj create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/AMEET.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/AmbientProperties.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/ArrayHolder.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/AttachableProperties.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/BamlTypes.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/Collections.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/ConverterNameRefMath.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/CpaClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/DestinationTypeConverterTypes.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/DrtXaml.snk create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/DummyCollections.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/Elements.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/FactoryProvider.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/IPVTClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/InitializationClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/MarkupExtensions.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/NSGO.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/NameScopes.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/NodeStream.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/ObjectReaderClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/ObsoleteClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/PropertyClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/TemplateClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/TestExpression.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/TestTemplate.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/TypeConverters.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/ValueSerializerClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/Xaml/CdfTemplateClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/XamlMarkupExtensionWriterClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/XamlObjectWriterClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/XamlTestClasses.csproj create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/XamlTextWriterClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/XmlDataHolder.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/XamlTestClasses/XmlNsClasses.cs create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/DrtXaml/dir.props create mode 100644 src/Microsoft.DotNet.Wpf/test/DRT/dir.props create mode 100644 src/Microsoft.DotNet.Wpf/test/Directory.Build.props create mode 100644 src/Microsoft.DotNet.Wpf/test/MultiTargeting.props create mode 100644 src/Microsoft.DotNet.Wpf/test/dir.props diff --git a/.gitignore b/.gitignore index e8a58417ca7..df7046cdc2c 100644 --- a/.gitignore +++ b/.gitignore @@ -52,7 +52,7 @@ BenchmarkDotNet.Artifacts/ project.lock.json project.fragment.lock.json artifacts/ -.dotnet/ +**/Properties/launchSettings.json # StyleCop StyleCopReport.xml @@ -179,7 +179,6 @@ PublishScripts/ # NuGet Packages *.nupkg -.packages/ # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. @@ -222,7 +221,7 @@ ClientBin/ *.publishsettings orleans.codegen.cs -# Including strong name files can present a security risk +# Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk @@ -318,7 +317,7 @@ __pycache__/ # OpenCover UI analysis results OpenCover/ -# Azure Stream Analytics local run output +# Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log @@ -327,5 +326,8 @@ ASALocalRun/ # NVidia Nsight GPU debugger configuration file *.nvuser -# MFractors (Xamarin productivity tool) working folder +# MFractors (Xamarin productivity tool) working folder .mfractor/ +/.dotnet +/.packages +/.tools/vswhere/2.5.2 diff --git a/Directory.Build.props b/Directory.Build.props index f81de84ed71..f5f3eb7dcb7 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,7 +2,20 @@ false + + + false + + + false + + true + + + + full + diff --git a/Directory.Build.targets b/Directory.Build.targets index 177d64c47ad..fcdc2c1ad0a 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,4 +1,6 @@ + + diff --git a/HelloWorld.sln b/HelloWorld.sln deleted file mode 100644 index 8d74c81f422..00000000000 --- a/HelloWorld.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27912.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloWorld", "HelloWorld\HelloWorld.csproj", "{0D23A41B-2626-4703-9E4A-87C07F69B0B2}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {0D23A41B-2626-4703-9E4A-87C07F69B0B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0D23A41B-2626-4703-9E4A-87C07F69B0B2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0D23A41B-2626-4703-9E4A-87C07F69B0B2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0D23A41B-2626-4703-9E4A-87C07F69B0B2}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {56D5F4DA-F710-4026-8F49-4A903BCAA9B5} - EndGlobalSection -EndGlobal diff --git a/HelloWorld/HelloWorld.csproj b/HelloWorld/HelloWorld.csproj deleted file mode 100644 index fdcf1895530..00000000000 --- a/HelloWorld/HelloWorld.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - Exe - netcoreapp2.0 - true - - - diff --git a/Microsoft.Dotnet.Wpf.sln b/Microsoft.Dotnet.Wpf.sln new file mode 100644 index 00000000000..fe16fae857b --- /dev/null +++ b/Microsoft.Dotnet.Wpf.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2048 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Xaml", "src\Microsoft.DotNet.Wpf\src\System.Xaml\System.Xaml.csproj", "{9AC36357-34B7-40A1-95CA-FE9F46D089A7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Debug|x64.ActiveCfg = Debug|x64 + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Debug|x64.Build.0 = Debug|x64 + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Debug|x86.ActiveCfg = Debug|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Debug|x86.Build.0 = Debug|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Release|Any CPU.Build.0 = Release|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Release|x64.ActiveCfg = Release|x64 + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Release|x64.Build.0 = Release|x64 + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Release|x86.ActiveCfg = Release|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {671D19D1-5F0E-4453-9D18-3A28AC0E8DEF} + EndGlobalSection +EndGlobal diff --git a/Packaging.targets b/Packaging.targets new file mode 100644 index 00000000000..c9854c7806b --- /dev/null +++ b/Packaging.targets @@ -0,0 +1,26 @@ + + + \ No newline at end of file diff --git a/Publishing.targets b/Publishing.targets new file mode 100644 index 00000000000..3603eeea84f --- /dev/null +++ b/Publishing.targets @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/SystemResources.props b/SystemResources.props new file mode 100644 index 00000000000..f7d5f38001f --- /dev/null +++ b/SystemResources.props @@ -0,0 +1,24 @@ + + + + + true + FxResources.$(AssemblyName).SR + true + + MS.Utility.SRID + System.SR + System.SR + MS.Internal.WindowsBase.SRID + Microsoft.Windows.Controls.SRID + System.SR + System.Windows.Xps.SRID + System.Windows.SRID + System.Windows.TrustUI.SRID + System.Windows.SRID + MS.Internal.PresentationCore.SRID + System.SRID + + + + diff --git a/Test.cmd b/Test.cmd new file mode 100644 index 00000000000..709c169ffc9 --- /dev/null +++ b/Test.cmd @@ -0,0 +1,3 @@ +@echo off +powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0eng\common\Build.ps1""" -test %*" +exit /b %ErrorLevel% \ No newline at end of file diff --git a/Tests.sln b/Tests.sln new file mode 100644 index 00000000000..35f104427ef --- /dev/null +++ b/Tests.sln @@ -0,0 +1,121 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2026 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DrtXaml.Tests", "src\Microsoft.DotNet.Wpf\test\DRT\DrtXaml\DrtXaml\DrtXaml.Tests.csproj", "{FAB114A2-2C6C-4372-A6BB-BC087B646E3A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestServices", "src\Microsoft.DotNet.Wpf\test\Common\TestServices\TestServices.csproj", "{387F3700-8C0B-4CEC-A68A-1725F656A249}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XamlTestClasses", "src\Microsoft.DotNet.Wpf\test\DRT\DrtXaml\XamlTestClasses\XamlTestClasses.csproj", "{3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XamlTestClasses.FriendWithKey", "src\Microsoft.DotNet.Wpf\test\DRT\DrtXaml\XamlTestClasses.FriendWithKey\XamlTestClasses.FriendWithKey.csproj", "{BA5AFF97-E993-49CB-BD2D-593F85E83FD5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XamlTestClasses.FriendWithoutKey", "src\Microsoft.DotNet.Wpf\test\DRT\DrtXaml\XamlTestClasses.FriendWithoutKey\XamlTestClasses.FriendWithoutKey.csproj", "{7D204145-BB36-4239-AD55-24DCE26BE997}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BamlTestClasses40", "src\Microsoft.DotNet.Wpf\test\DRT\DrtXaml\BamlTestClasses40\BamlTestClasses40.csproj", "{2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BamlAvoidXmlTest", "src\Microsoft.DotNet.Wpf\test\DRT\DrtXaml\BamlAvoidXmlTest\BamlAvoidXmlTest.csproj", "{9163F98E-E941-45F5-9A57-47F375F50333}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FAB114A2-2C6C-4372-A6BB-BC087B646E3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FAB114A2-2C6C-4372-A6BB-BC087B646E3A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FAB114A2-2C6C-4372-A6BB-BC087B646E3A}.Debug|x64.ActiveCfg = Debug|x64 + {FAB114A2-2C6C-4372-A6BB-BC087B646E3A}.Debug|x64.Build.0 = Debug|x64 + {FAB114A2-2C6C-4372-A6BB-BC087B646E3A}.Debug|x86.ActiveCfg = Debug|Any CPU + {FAB114A2-2C6C-4372-A6BB-BC087B646E3A}.Debug|x86.Build.0 = Debug|Any CPU + {FAB114A2-2C6C-4372-A6BB-BC087B646E3A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FAB114A2-2C6C-4372-A6BB-BC087B646E3A}.Release|Any CPU.Build.0 = Release|Any CPU + {FAB114A2-2C6C-4372-A6BB-BC087B646E3A}.Release|x64.ActiveCfg = Release|x64 + {FAB114A2-2C6C-4372-A6BB-BC087B646E3A}.Release|x64.Build.0 = Release|x64 + {FAB114A2-2C6C-4372-A6BB-BC087B646E3A}.Release|x86.ActiveCfg = Release|Any CPU + {FAB114A2-2C6C-4372-A6BB-BC087B646E3A}.Release|x86.Build.0 = Release|Any CPU + {387F3700-8C0B-4CEC-A68A-1725F656A249}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {387F3700-8C0B-4CEC-A68A-1725F656A249}.Debug|Any CPU.Build.0 = Debug|Any CPU + {387F3700-8C0B-4CEC-A68A-1725F656A249}.Debug|x64.ActiveCfg = Debug|x64 + {387F3700-8C0B-4CEC-A68A-1725F656A249}.Debug|x64.Build.0 = Debug|x64 + {387F3700-8C0B-4CEC-A68A-1725F656A249}.Debug|x86.ActiveCfg = Debug|Any CPU + {387F3700-8C0B-4CEC-A68A-1725F656A249}.Debug|x86.Build.0 = Debug|Any CPU + {387F3700-8C0B-4CEC-A68A-1725F656A249}.Release|Any CPU.ActiveCfg = Release|Any CPU + {387F3700-8C0B-4CEC-A68A-1725F656A249}.Release|Any CPU.Build.0 = Release|Any CPU + {387F3700-8C0B-4CEC-A68A-1725F656A249}.Release|x64.ActiveCfg = Release|x64 + {387F3700-8C0B-4CEC-A68A-1725F656A249}.Release|x64.Build.0 = Release|x64 + {387F3700-8C0B-4CEC-A68A-1725F656A249}.Release|x86.ActiveCfg = Release|Any CPU + {387F3700-8C0B-4CEC-A68A-1725F656A249}.Release|x86.Build.0 = Release|Any CPU + {3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}.Debug|x64.ActiveCfg = Debug|x64 + {3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}.Debug|x64.Build.0 = Debug|x64 + {3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}.Debug|x86.ActiveCfg = Debug|Any CPU + {3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}.Debug|x86.Build.0 = Debug|Any CPU + {3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}.Release|Any CPU.Build.0 = Release|Any CPU + {3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}.Release|x64.ActiveCfg = Release|x64 + {3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}.Release|x64.Build.0 = Release|x64 + {3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}.Release|x86.ActiveCfg = Release|Any CPU + {3C1FC36C-E3E6-4EED-9ECA-CFF2EB950486}.Release|x86.Build.0 = Release|Any CPU + {BA5AFF97-E993-49CB-BD2D-593F85E83FD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA5AFF97-E993-49CB-BD2D-593F85E83FD5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA5AFF97-E993-49CB-BD2D-593F85E83FD5}.Debug|x64.ActiveCfg = Debug|x64 + {BA5AFF97-E993-49CB-BD2D-593F85E83FD5}.Debug|x64.Build.0 = Debug|x64 + {BA5AFF97-E993-49CB-BD2D-593F85E83FD5}.Debug|x86.ActiveCfg = Debug|Any CPU + {BA5AFF97-E993-49CB-BD2D-593F85E83FD5}.Debug|x86.Build.0 = Debug|Any CPU + {BA5AFF97-E993-49CB-BD2D-593F85E83FD5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA5AFF97-E993-49CB-BD2D-593F85E83FD5}.Release|Any CPU.Build.0 = Release|Any CPU + {BA5AFF97-E993-49CB-BD2D-593F85E83FD5}.Release|x64.ActiveCfg = Release|x64 + {BA5AFF97-E993-49CB-BD2D-593F85E83FD5}.Release|x64.Build.0 = Release|x64 + {BA5AFF97-E993-49CB-BD2D-593F85E83FD5}.Release|x86.ActiveCfg = Release|Any CPU + {BA5AFF97-E993-49CB-BD2D-593F85E83FD5}.Release|x86.Build.0 = Release|Any CPU + {7D204145-BB36-4239-AD55-24DCE26BE997}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7D204145-BB36-4239-AD55-24DCE26BE997}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D204145-BB36-4239-AD55-24DCE26BE997}.Debug|x64.ActiveCfg = Debug|x64 + {7D204145-BB36-4239-AD55-24DCE26BE997}.Debug|x64.Build.0 = Debug|x64 + {7D204145-BB36-4239-AD55-24DCE26BE997}.Debug|x86.ActiveCfg = Debug|Any CPU + {7D204145-BB36-4239-AD55-24DCE26BE997}.Debug|x86.Build.0 = Debug|Any CPU + {7D204145-BB36-4239-AD55-24DCE26BE997}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7D204145-BB36-4239-AD55-24DCE26BE997}.Release|Any CPU.Build.0 = Release|Any CPU + {7D204145-BB36-4239-AD55-24DCE26BE997}.Release|x64.ActiveCfg = Release|x64 + {7D204145-BB36-4239-AD55-24DCE26BE997}.Release|x64.Build.0 = Release|x64 + {7D204145-BB36-4239-AD55-24DCE26BE997}.Release|x86.ActiveCfg = Release|Any CPU + {7D204145-BB36-4239-AD55-24DCE26BE997}.Release|x86.Build.0 = Release|Any CPU + {2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}.Debug|x64.ActiveCfg = Debug|x64 + {2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}.Debug|x64.Build.0 = Debug|x64 + {2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}.Debug|x86.ActiveCfg = Debug|Any CPU + {2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}.Debug|x86.Build.0 = Debug|Any CPU + {2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}.Release|Any CPU.Build.0 = Release|Any CPU + {2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}.Release|x64.ActiveCfg = Release|x64 + {2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}.Release|x64.Build.0 = Release|x64 + {2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}.Release|x86.ActiveCfg = Release|Any CPU + {2127AC4D-78F4-44BE-A93F-8872EA9A8BB2}.Release|x86.Build.0 = Release|Any CPU + {9163F98E-E941-45F5-9A57-47F375F50333}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9163F98E-E941-45F5-9A57-47F375F50333}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9163F98E-E941-45F5-9A57-47F375F50333}.Debug|x64.ActiveCfg = Debug|x64 + {9163F98E-E941-45F5-9A57-47F375F50333}.Debug|x64.Build.0 = Debug|x64 + {9163F98E-E941-45F5-9A57-47F375F50333}.Debug|x86.ActiveCfg = Debug|Any CPU + {9163F98E-E941-45F5-9A57-47F375F50333}.Debug|x86.Build.0 = Debug|Any CPU + {9163F98E-E941-45F5-9A57-47F375F50333}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9163F98E-E941-45F5-9A57-47F375F50333}.Release|Any CPU.Build.0 = Release|Any CPU + {9163F98E-E941-45F5-9A57-47F375F50333}.Release|x64.ActiveCfg = Release|x64 + {9163F98E-E941-45F5-9A57-47F375F50333}.Release|x64.Build.0 = Release|x64 + {9163F98E-E941-45F5-9A57-47F375F50333}.Release|x86.ActiveCfg = Release|Any CPU + {9163F98E-E941-45F5-9A57-47F375F50333}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B4340004-DAC0-497D-B69D-CFA7CD93F567} + EndGlobalSection +EndGlobal diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 0496d4a33c3..e94cd9aa418 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -2,9 +2,9 @@ - + https://github.com/dotnet/arcade - ef208f75c0494f47bf79a317773adcb398c35f92 + 7b0a1f028490bbf18ab1565998719315f2de22e7 \ No newline at end of file diff --git a/eng/Versions.props b/eng/Versions.props index 8df0a2de891..c3bfa1a6052 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,7 +1,18 @@ - 1.0.0 + 3.0.0 prerelease + + 4.8.$(VersionSuffixDateStamp).0 + 4.8.0.0 + + 4.0.0.0 + + 4.5.0 + 4.3.0 + 2.4.0 + 2.4.0 + 2.4.0 \ No newline at end of file diff --git a/eng/build.yml b/eng/build.yml index d59d128aac1..4e36851dd15 100644 --- a/eng/build.yml +++ b/eng/build.yml @@ -40,7 +40,7 @@ phases: # Right now a manual build of a random branch would get published alongside the normal branch artifacts. _PublishBlobFeedUrl: https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json _SignArgs: /p:DotNetSignType=$(_SignType) /p:TeamName=$(_TeamName) - _PublishArgs: /p:DotNetPublishBlobFeedKey=$(dotnetfeed-storage-access-key-1) + _PublishArgs: /p:DotNetPublishBlobFeedKey=$(dotnetfeed-storage-access-key-1) /p:DotNetPublishBlobFeedUrl=$(_PublishBlobFeedUrl) /p:DotNetPublishToBlobFeed=$(_DotNetPublishToBlobFeed) /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) @@ -67,18 +67,10 @@ phases: $(_PublishArgs) $(_SignArgs) $(_OfficialBuildIdArgs) + /p:Platform=$(_Platform) /p:IsShipping=$(IsShipping) displayName: Windows Build / Publish condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT')) - - script: eng/common/cibuild.sh - --configuration $(_BuildConfig) - --prepareMachine - $(_PublishArgs) - $(_SignArgs) - $(_OfficialBuildIdArgs) - displayName: Unix Build / Publish - condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) - - task: PublishBuildArtifacts@1 displayName: Publish Logs to VSTS inputs: diff --git a/eng/common/templates/phases/publish-build-assets.yml b/eng/common/templates/phases/publish-build-assets.yml index c9381cf1044..613e3723d6b 100644 --- a/eng/common/templates/phases/publish-build-assets.yml +++ b/eng/common/templates/phases/publish-build-assets.yml @@ -11,7 +11,7 @@ phases: dependsOn: ${{ parameters.dependsOn }} queue: ${{ parameters.queue }} variables: - config: ${{ parameters.configuration }} + _BuildConfig: ${{ parameters.configuration }} steps: - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: DownloadBuildArtifacts@0 @@ -32,7 +32,16 @@ phases: /p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests' /p:BuildAssetRegistryToken=$(MaestroAccessToken) /p:MaestroApiEndpoint=https://maestro-prod.westus2.cloudapp.azure.com - /p:Configuration=$(config) + /p:Configuration=$(_BuildConfig) + -msbuildEngine dotnet displayName: Publish Build Assets condition: ${{ parameters.condition }} continueOnError: ${{ parameters.continueOnError }} + - task: PublishBuildArtifacts@1 + displayName: Publish Logs to VSTS + inputs: + PathtoPublish: '$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)' + PublishLocation: Container + ArtifactName: $(Agent.Os)_Asset_Registry_Publish + continueOnError: true + condition: always() \ No newline at end of file diff --git a/eng/common/templates/steps/helix-publish.yml b/eng/common/templates/steps/helix-publish.yml index f14546730e3..4e82372bbd8 100644 --- a/eng/common/templates/steps/helix-publish.yml +++ b/eng/common/templates/steps/helix-publish.yml @@ -23,7 +23,7 @@ steps: command: custom projects: eng/common/helixpublish.proj custom: msbuild - arguments: '/t:test /p:Language=msbuild' + arguments: '/t:test /p:Language=msbuild /bl:$(Build.SourcesDirectory)\artifacts\log\$(_BuildConfig)\sendtohelix.binlog' displayName: Send job to Helix env: HelixSource: ${{ parameters.HelixSource }} diff --git a/global.json b/global.json index 7ebfe013766..0588b4762cd 100644 --- a/global.json +++ b/global.json @@ -1,8 +1,9 @@ { "tools": { - "dotnet": "2.1.300" + "dotnet":"3.0.100-preview-009736", + "vswhere":"2.5.2" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.18526.8" + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.18559.6" } } \ No newline at end of file diff --git a/src/Directory.Build.Props b/src/Directory.Build.Props new file mode 100644 index 00000000000..c7d7f5865a6 --- /dev/null +++ b/src/Directory.Build.Props @@ -0,0 +1,4 @@ + + + + diff --git a/src/Microsoft.DotNet.Wpf/Directory.Build.Props b/src/Microsoft.DotNet.Wpf/Directory.Build.Props new file mode 100644 index 00000000000..c7d7f5865a6 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/Directory.Build.Props @@ -0,0 +1,4 @@ + + + + diff --git a/src/Microsoft.DotNet.Wpf/src/Common/src/System/SR.cs b/src/Microsoft.DotNet.Wpf/src/Common/src/System/SR.cs new file mode 100644 index 00000000000..7893aefc2a5 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Common/src/System/SR.cs @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Resources; +using System.Runtime.CompilerServices; + +#if CUSTOM_SR_NAMESPACE +namespace #CUSTOM_SR_NAMESPACE# +#else +namespace System +#endif +{ +#if CUSTOM_SR_CLASSNAME + internal partial class #CUSTOM_SR_CLASSNAME# +#else + + internal partial class SR +#endif + { + private static ResourceManager ResourceManager => SRID.ResourceManager; + + // This method is used to decide if we need to append the exception message parameters to the message when calling SR.Format. + // by default it returns false. + [MethodImpl(MethodImplOptions.NoInlining)] + private static bool UsingResourceKeys() + { + return false; + } + + internal static string GetResourceString(string resourceKey, string defaultString) + { + string resourceString = null; + try { resourceString = ResourceManager.GetString(resourceKey); } + catch (MissingManifestResourceException) { } + + if (defaultString != null && resourceKey.Equals(resourceString, StringComparison.Ordinal)) + { + return defaultString; + } + + return resourceString; + } + + internal static string Format(string resourceFormat, params object[] args) + { + if (args != null) + { + if (UsingResourceKeys()) + { + return resourceFormat + string.Join(", ", args); + } + + return string.Format(resourceFormat, args); + } + + return resourceFormat; + } + + internal static string Format(string resourceFormat, object p1) + { + if (UsingResourceKeys()) + { + return string.Join(", ", resourceFormat, p1); + } + + return string.Format(resourceFormat, p1); + } + + internal static string Format(string resourceFormat, object p1, object p2) + { + if (UsingResourceKeys()) + { + return string.Join(", ", resourceFormat, p1, p2); + } + + return string.Format(resourceFormat, p1, p2); + } + + internal static string Format(string resourceFormat, object p1, object p2, object p3) + { + if (UsingResourceKeys()) + { + return string.Join(", ", resourceFormat, p1, p2, p3); + } + + return string.Format(resourceFormat, p1, p2, p3); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Wpf/src/Directory.Build.Props b/src/Microsoft.DotNet.Wpf/src/Directory.Build.Props new file mode 100644 index 00000000000..3756028cb62 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Directory.Build.Props @@ -0,0 +1,10 @@ + + + + + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + true + $(MSBuildThisFileDirectory)Shared\ + $(MSBuildThisFileDirectory)Common\ + + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/CriticalExceptions.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/CriticalExceptions.cs new file mode 100644 index 00000000000..54e88fa206a --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/CriticalExceptions.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +#if PBTCOMPILER +namespace MS.Internal.Markup +#elif SYSTEM_XAML +namespace System.Xaml +#else +using MS.Internal.WindowsBase; // FriendAccessAllowed +namespace MS.Internal +#endif +{ + #if !PBTCOMPILER && !SYSTEM_XAML + [FriendAccessAllowed] + #endif + internal static class CriticalExceptions + { + // these are all the exceptions considered critical by PreSharp + #if !PBTCOMPILER && !SYSTEM_XAML + [FriendAccessAllowed] + #endif + internal static bool IsCriticalException(Exception ex) + { + ex = Unwrap(ex); + + return ex is NullReferenceException || + ex is StackOverflowException || + ex is OutOfMemoryException || + ex is System.Threading.ThreadAbortException || + ex is System.Runtime.InteropServices.SEHException || + ex is System.Security.SecurityException; + } + + // these are exceptions that we should treat as critical when they + // arise during callbacks into application code + #if !PBTCOMPILER && !SYSTEM_XAML + [FriendAccessAllowed] + internal static bool IsCriticalApplicationException(Exception ex) + { + ex = Unwrap(ex); + + return ex is StackOverflowException || + ex is OutOfMemoryException || + ex is System.Threading.ThreadAbortException || + ex is System.Security.SecurityException; + } + #endif + + #if !PBTCOMPILER && !SYSTEM_XAML + [FriendAccessAllowed] + #endif + internal static Exception Unwrap(Exception ex) + { + // for certain types of exceptions, we care more about the inner + // exception + while (ex.InnerException != null && + ( ex is System.Reflection.TargetInvocationException + )) + { + ex = ex.InnerException; + } + + return ex; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/FriendAccessAllowedAttribute.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/FriendAccessAllowedAttribute.cs new file mode 100644 index 00000000000..6f0aa7fd762 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/FriendAccessAllowedAttribute.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Description: Implementation of a FriendAccessAllowedAttribute attribute that is used to mark internal metadata +// that is allowed to be accessed from friend assemblies. + + +using System; + +#if WINDOWS_BASE +namespace MS.Internal.WindowsBase +#elif PRESENTATION_CORE +namespace MS.Internal.PresentationCore +#elif PRESENTATIONFRAMEWORK +namespace MS.Internal.PresentationFramework +#elif PRESENTATION_CFF_RASTERIZER +namespace MS.Internal.PresentationCffRasterizer +#elif PRESENTATIONUI +namespace MS.Internal.PresentationUI +#elif UIAUTOMATIONTYPES +namespace MS.Internal.UIAutomationTypes +#elif DRT +namespace MS.Internal.Drt +#elif SYSTEM_XAML +namespace MS.Internal.WindowsBase //current copy of XmlMarkupCompatibilityReader uses this ns for FAAA. +#else +#error Attempt to define FriendAccessAllowedAttribute in an unknown assembly. +namespace MS.Internal.YourAssemblyName +#endif +{ + [AttributeUsage( + AttributeTargets.Class | + AttributeTargets.Property | + AttributeTargets.Field | + AttributeTargets.Method | + AttributeTargets.Struct | + AttributeTargets.Enum | + AttributeTargets.Interface | + AttributeTargets.Delegate | + AttributeTargets.Constructor, + AllowMultiple = false, + Inherited = true) + ] + internal sealed class FriendAccessAllowedAttribute : Attribute + { + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/SafeSecurityHelper.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/SafeSecurityHelper.cs new file mode 100644 index 00000000000..70686bf7b48 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/SafeSecurityHelper.cs @@ -0,0 +1,530 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Purpose: Helper functions that require elevation but are safe to use. +// History: +// 10/15/04: Microsoft Created + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Security; +using System.Security.Permissions; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +#if SYSTEM_XAML +using TypeConverterHelper = System.Xaml.TypeConverterHelper; +#else +using Microsoft.Win32; +using MS.Win32; +using TypeConverterHelper = System.Windows.Markup.TypeConverterHelper; +#endif +#if PRESENTATIONFRAMEWORK + using System.Windows; + using System.Windows.Media; +#endif + +// The SafeSecurityHelper class differs between assemblies and could not actually be +// shared, so it is duplicated across namespaces to prevent name collision. +#if WINDOWS_BASE +namespace MS.Internal.WindowsBase +#elif PRESENTATION_CORE +namespace MS.Internal.PresentationCore +#elif PRESENTATIONFRAMEWORK +namespace MS.Internal.PresentationFramework +#elif REACHFRAMEWORK +namespace MS.Internal.ReachFramework +#elif DRT +namespace MS.Internal.Drt +#elif SYSTEM_XAML +namespace System.Xaml +#else +#error Class is being used from an unknown assembly. +#endif +{ + internal static partial class SafeSecurityHelper + { +#if PRESENTATION_CORE + /// + /// Given a rectangle with coords in local screen coordinates. + /// Return the rectangle in global screen coordinates. + /// + /// + /// Critical - calls a critical function. + /// TreatAsSafe - handing out a transformed rect is considered safe. + /// + /// Although we are calling a function that passes an array, and no. of elements. + /// We limit this call to only call this function with a 2 as the count of elements. + /// Thereby containing any potential for the call to Win32 to cause a buffer overrun. + /// + [SecurityCritical, SecurityTreatAsSafe ] + internal static void TransformLocalRectToScreen(HandleRef hwnd, ref NativeMethods.RECT rcWindowCoords) + { + int retval = MS.Internal.WindowsBase.NativeMethodsSetLastError.MapWindowPoints(hwnd , new HandleRef(null, IntPtr.Zero), ref rcWindowCoords, 2); + int win32Err = Marshal.GetLastWin32Error(); + if(retval == 0 && win32Err != 0) + { + throw new System.ComponentModel.Win32Exception(win32Err); + } + } +#endif + +#if PRESENTATION_CORE || PRESENTATIONFRAMEWORK ||REACHFRAMEWORK || DEBUG + +#if !WINDOWS_BASE && !SYSTEM_XAML + /// + /// Given an assembly, returns the partial name of the assembly. + /// + /// + /// This code used to perform an elevation but no longer needs to. + /// The method is being kept in this class to ease auditing and + /// should have a security review if changed. + /// The string returned does not contain path information. + /// This code is duplicated in SafeSecurityHelperPBT.cs. + /// + internal static string GetAssemblyPartialName(Assembly assembly) + { + AssemblyName name = new AssemblyName(assembly.FullName); + string partialName = name.Name; + return (partialName != null) ? partialName : String.Empty; + } +#endif + +#endif + +#if PRESENTATIONFRAMEWORK + + /// + /// Get the full assembly name by combining the partial name passed in + /// with everything else from proto assembly. + /// + /// + /// This code used to perform an elevation but no longer needs to. + /// The method is being kept in this class to ease auditing and + /// should have a security review if changed. + /// The string returned does not contain path information. + /// + internal static string GetFullAssemblyNameFromPartialName( + Assembly protoAssembly, + string partialName) + { + AssemblyName name = new AssemblyName(protoAssembly.FullName); + name.Name = partialName; + return name.FullName; + } + + /// + /// Critical: This code accesses PresentationSource which is critical but does not + /// expose it. + /// TreatAsSafe: PresentationSource is not exposed and Client to Screen co-ordinates is + /// safe to expose + /// + [SecurityCritical,SecurityTreatAsSafe] + internal static Point ClientToScreen(UIElement relativeTo, Point point) + { + GeneralTransform transform; + PresentationSource source = PresentationSource.CriticalFromVisual(relativeTo); + + if (source == null) + { + return new Point(double.NaN, double.NaN); + } + transform = relativeTo.TransformToAncestor(source.RootVisual); + Point ptRoot; + transform.TryTransform(point, out ptRoot); + Point ptClient = PointUtil.RootToClient(ptRoot, source); + Point ptScreen = PointUtil.ClientToScreen(ptClient, source); + + return ptScreen; + } +#endif // PRESENTATIONFRAMEWORK + +#if WINDOWS_BASE || PRESENTATION_CORE || SYSTEM_XAML + + // Cache of Assembly -> AssemblyName, because calling new AssemblyName() is expensive. + // If the assembly is static, the key is the assembly; if it's dynamic, the key is a WeakRefKey + // pointing to the assembly, so we don't root collectible assemblies. + // + // This cache is bound (gated) by the number of assemblies in the appdomain. + // We use a callback on GC to purge out collected assemblies, so we don't grow indefinitely. + // + static Dictionary _assemblies; // get key via GetKeyForAssembly + static object syncObject = new object(); + static bool _isGCCallbackPending; + + // PERF: Cache delegate for CleanupCollectedAssemblies to avoid allocating it each time. + static readonly WaitCallback _cleanupCollectedAssemblies = CleanupCollectedAssemblies; + + /// + /// This function iterates through the assemblies loaded in the current + /// AppDomain and finds one that has the same assembly name passed in. + /// + /// + /// The method is being kept in this class to ease auditing and + /// should have a security review if changed. + /// + /// WARNING! Don't use this method for retrievals of assemblies that + /// should rely on a strong match with the given assembly name + /// since this method allows assemblies with the same short name + /// to be returned even when other name parts are different. + /// + /// E.g. AssemblyShortName + /// matches AssemblyShortName, Version=2.0.0.0, Culture=en-us, PublicKeyToken=b03f5f7f11d50a3a + /// + internal static Assembly GetLoadedAssembly(AssemblyName assemblyName) + { + Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); + + Version reqVersion = assemblyName.Version; + CultureInfo reqCulture = assemblyName.CultureInfo; + byte[] reqKeyToken = assemblyName.GetPublicKeyToken(); + + for (int i = assemblies.Length - 1; i >= 0; i--) + { + AssemblyName curAsmName = GetAssemblyName(assemblies[i]); + Version curVersion = curAsmName.Version; + CultureInfo curCulture = curAsmName.CultureInfo; + byte[] curKeyToken = curAsmName.GetPublicKeyToken(); + + if ( (String.Compare(curAsmName.Name, assemblyName.Name, true, TypeConverterHelper.InvariantEnglishUS) == 0) && + (reqVersion == null || reqVersion.Equals(curVersion)) && + (reqCulture == null || reqCulture.Equals(curCulture)) && + (reqKeyToken == null || IsSameKeyToken(reqKeyToken, curKeyToken) ) ) + { + return assemblies[i]; + } + } + return null; + } + + static AssemblyName GetAssemblyName(Assembly assembly) + { + object key = assembly.IsDynamic ? (object)new WeakRefKey(assembly) : assembly; + lock (syncObject) + { + AssemblyName result; + if (_assemblies == null) + { + _assemblies = new Dictionary(); + } + else + { + if (_assemblies.TryGetValue(key, out result)) + { + return result; + } + } + // + // We use AssemblyName ctor here because GetName demands FileIOPermission + // and does load more than just the required information. + // Essentially we use AssemblyName just to help parsing the name, version, culture + // and public key token from the assembly's name. + // + result = new AssemblyName(assembly.FullName); + _assemblies.Add(key, result); + if (assembly.IsDynamic && !_isGCCallbackPending) + { + // Make sure we clean up the cache if/when this dynamic assembly is GCed + GCNotificationToken.RegisterCallback(_cleanupCollectedAssemblies, null); + _isGCCallbackPending = true; + } + return result; + } + } + + // After a GC, clean up the weakrefs to any collected dynamic assemblies + static void CleanupCollectedAssemblies(object state) // dummy parameter required by WaitCallback definition + { + bool foundLiveDynamicAssemblies = false; + List keysToRemove = null; + lock (syncObject) + { + foreach (object key in _assemblies.Keys) + { + WeakReference weakRef = key as WeakReference; + if (weakRef == null) + { + continue; + } + if (weakRef.IsAlive) + { + // There is a weak ref that is still alive, register another GC callback for next time + foundLiveDynamicAssemblies = true; + } + else + { + // The target has been collected, add it to our list of keys to remove + if (keysToRemove == null) + { + keysToRemove = new List(); + } + keysToRemove.Add(key); + } + } + if (keysToRemove != null) + { + foreach (object key in keysToRemove) + { + _assemblies.Remove(key); + } + } + if (foundLiveDynamicAssemblies) + { + GCNotificationToken.RegisterCallback(_cleanupCollectedAssemblies, null); + } + else + { + _isGCCallbackPending = false; + } + } + } + +#endif // WINDOWS_BASE || PRESENTATION_CORE || SYSTEM_XAML + + // + // Determine if two Public Key Tokens are the same. + // +#if !REACHFRAMEWORK +#if PRESENTATIONFRAMEWORK || SYSTEM_XAML || PRESENTATION_CORE + internal +#else + private +#endif + static bool IsSameKeyToken(byte[] reqKeyToken, byte[] curKeyToken) + { + bool isSame = false; + + if (reqKeyToken == null && curKeyToken == null) + { + // Both Key Tokens are not set, treat them as same. + isSame = true; + } + else if (reqKeyToken != null && curKeyToken != null) + { + // Both KeyTokens are set. + if (reqKeyToken.Length == curKeyToken.Length) + { + isSame = true; + + for (int i = 0; i < reqKeyToken.Length; i++) + { + if (reqKeyToken[i] != curKeyToken[i]) + { + isSame = false; + break; + } + } + } + } + + return isSame; + } +#endif //!REACHFRAMEWORK + +#if PRESENTATION_CORE || PRESENTATIONFRAMEWORK + // enum to choose between the various keys + internal enum KeyToRead + { + WebBrowserDisable = 0x01 , + MediaAudioDisable = 0x02 , + MediaVideoDisable = 0x04 , + MediaImageDisable = 0x08 , + MediaAudioOrVideoDisable = KeyToRead.MediaVideoDisable | KeyToRead.MediaAudioDisable , + ScriptInteropDisable = 0x10 , + } + + /// + /// Critical: This code elevates to access registry + /// TreatAsSafe: The information it exposes is safe to give out and all it does is read a specific key + /// + [SecurityCritical,SecurityTreatAsSafe] + internal static bool IsFeatureDisabled(KeyToRead key) + { + string regValue = null; + bool fResult = false; + + switch (key) + { + case KeyToRead.WebBrowserDisable: + regValue = RegistryKeys.value_WebBrowserDisallow; + break; + case KeyToRead.MediaAudioDisable: + regValue = RegistryKeys.value_MediaAudioDisallow; + break; + case KeyToRead.MediaVideoDisable: + regValue = RegistryKeys.value_MediaVideoDisallow; + break; + case KeyToRead.MediaImageDisable: + regValue = RegistryKeys.value_MediaImageDisallow; + break; + case KeyToRead.MediaAudioOrVideoDisable: + regValue = RegistryKeys.value_MediaAudioDisallow; + break; + case KeyToRead.ScriptInteropDisable: + regValue = RegistryKeys.value_ScriptInteropDisallow; + break; + default:// throw exception for invalid key + throw(new System.ArgumentException(key.ToString())); + + } + + RegistryKey featureKey; + //Assert for read access to HKLM\Software\Microsoft\Windows\Avalon + RegistryPermission regPerm = new RegistryPermission(RegistryPermissionAccess.Read,"HKEY_LOCAL_MACHINE\\"+RegistryKeys.WPF_Features);//BlessedAssert + regPerm.Assert();//BlessedAssert + try + { + object obj = null; + bool keyValue = false; + // open the key and read the value + featureKey = Registry.LocalMachine.OpenSubKey(RegistryKeys.WPF_Features); + if (featureKey != null) + { + // If key exists and value is 1 return true else false + obj = featureKey.GetValue(regValue); + keyValue = obj is int && ((int)obj == 1); + if (keyValue) + { + fResult = true; + } + + // special case for audio and video since they can be orred + // this is in the condition that audio is enabled since that is + // the path that MediaAudioVideoDisable defaults to + // This is purely to optimize perf on the number of calls to assert + // in the media or audio scenario. + + if ((fResult == false) && (key == KeyToRead.MediaAudioOrVideoDisable)) + { + regValue = RegistryKeys.value_MediaVideoDisallow; + // If key exists and value is 1 return true else false + obj = featureKey.GetValue(regValue); + keyValue = obj is int && ((int)obj == 1); + if (keyValue) + { + fResult = true; + } + } + } + } + finally + { + RegistryPermission.RevertAssert(); + } + return fResult; + } +#endif //PRESENTATIONCORE||PRESENTATIONFRAMEWORK + +#if PRESENTATION_CORE + + /// + /// This function is a wrapper for CultureInfo.GetCultureInfoByIetfLanguageTag(). + /// The wrapper works around a bug in that routine, which causes it to throw + /// a SecurityException in Partial Trust. + /// + /// + /// Critical: This code elevates to access registry + /// TreatAsSafe: The information it exposes is safe to give out and all it does is read a specific key + /// + [SecurityCritical,SecurityTreatAsSafe] + static internal CultureInfo GetCultureInfoByIetfLanguageTag(string languageTag) + { + CultureInfo culture = null; + + RegistryPermission regPerm = new RegistryPermission(RegistryPermissionAccess.Read, RegistryKeys.HKLM_IetfLanguage);//BlessedAssert + regPerm.Assert();//BlessedAssert + try + { + culture = CultureInfo.GetCultureInfoByIetfLanguageTag(languageTag); + } + finally + { + RegistryPermission.RevertAssert(); + } + return culture; + } +#endif //PRESENTATIONCORE + + internal const string IMAGE = "image"; + } + +#if WINDOWS_BASE || PRESENTATION_CORE || SYSTEM_XAML + // for use as the key to a dictionary, when the "real" key is an object + // that we should not keep alive by a strong reference. + class WeakRefKey : WeakReference + { + public WeakRefKey(object target) + :base(target) + { + Debug.Assert(target != null); + _hashCode = target.GetHashCode(); + } + + public override int GetHashCode() + { + return _hashCode; + } + + public override bool Equals(object o) + { + WeakRefKey weakRef = o as WeakRefKey; + if (weakRef != null) + { + object target1 = Target; + object target2 = weakRef.Target; + + if (target1 != null && target2 != null) + { + return (target1 == target2); + } + } + return base.Equals(o); + } + + public static bool operator ==(WeakRefKey left, WeakRefKey right) + { + if (object.ReferenceEquals(left, null)) + { + return object.ReferenceEquals(right, null); + } + return left.Equals(right); + } + + public static bool operator !=(WeakRefKey left, WeakRefKey right) + { + return !(left == right); + } + + int _hashCode; // cache target's hashcode, lest it get GC'd out from under us + } + + // This cleanup token will be immediately thrown away and as a result it will + // (a couple of GCs later) make it into the finalization queue and when finalized + // will kick off a thread-pool job that you can use to purge a weakref cache. + class GCNotificationToken + { + WaitCallback callback; + object state; + + GCNotificationToken(WaitCallback callback, object state) + { + this.callback = callback; + this.state = state; + } + + ~GCNotificationToken() + { + // Schedule cleanup + ThreadPool.QueueUserWorkItem(callback, state); + } + + internal static void RegisterCallback(WaitCallback callback, object state) + { + new GCNotificationToken(callback, state); + } + } +#endif +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/SecurityCriticalDataForSet.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/SecurityCriticalDataForSet.cs new file mode 100644 index 00000000000..360c0b4002a --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/SecurityCriticalDataForSet.cs @@ -0,0 +1,94 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// +// Description: +// This is a helper class to facilate the storage of data that's Critical for set. +// The data itself is not information disclosure but the value controls a critical +// operation. +// +// For example a filepath variable might control what part of the file system the +// code gets access to. +// +// History: +// 01/30/05 : Microsoft Created. +// +using System ; +using System.Security ; + +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif PRESENTATIONUI + using MS.Internal.PresentationUI; +#elif UIAUTOMATIONTYPES + using MS.Internal.UIAutomationTypes; +#elif DRT + using MS.Internal.Drt; +#elif SYSTEM_XAML + using MS.Internal.WindowsBase; +#else +#error Attempt to use FriendAccessAllowedAttribute from an unknown assembly. +using MS.Internal.YourAssemblyName; +#endif + +#if SYSTEM_XAML +namespace MS.Internal.Xaml +#else +namespace MS.Internal +#endif +{ + [FriendAccessAllowed] // Built into Base, also used by Core and Framework. + [Serializable] + internal struct SecurityCriticalDataForSet + { + /// + /// Critical - "by definition" - this class is intended only for data that's + /// Critical for setting. + /// + [SecurityCritical] + internal SecurityCriticalDataForSet(T value) + { + _value = value; + } + + /// + /// Critical - Setter is Critical "by definition" - this class is intended only + /// for data that's Critical for setting. + /// Safe - get is safe by definition. + /// Not Safe - set is not safe by definition. + /// + internal T Value + { + #if DEBUG + [System.Diagnostics.DebuggerStepThrough] + #endif + [SecurityCritical, SecurityTreatAsSafe] + get + { + return _value; + } + + #if DEBUG + [System.Diagnostics.DebuggerStepThrough] + #endif + [SecurityCritical] + set + { + _value = value; + } + } + + /// + /// Critical - by definition as this data is Critical for set. + /// > + [SecurityCritical] + private T _value; + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Context/XamlContextStack.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Context/XamlContextStack.cs new file mode 100644 index 00000000000..71e6fc7cdaf --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Context/XamlContextStack.cs @@ -0,0 +1,160 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using System.Globalization; + +namespace MS.Internal.Xaml.Context +{ + //This stack has the following features: + // 1) it recycles frames + // 2) it is , and avoids activator.createinstance with the creationDelegate + class XamlContextStack where T : XamlFrame + { + private int _depth = -1; + T _currentFrame = null; + T _recycledFrame = null; + Func _creationDelegate; + + public XamlContextStack(Func creationDelegate) + { + _creationDelegate = creationDelegate; + Grow(); + _depth = 0; + Debug.Assert(CurrentFrame != null); + Debug.Assert(CurrentFrame.Depth == Depth); + } + + public XamlContextStack(XamlContextStack source, bool copy) + { + _creationDelegate = source._creationDelegate; + _depth = source.Depth; + if (!copy) + { + _currentFrame = source.CurrentFrame; + } + else + { + T iteratorFrame = source.CurrentFrame; + T lastFrameInNewStack = null; + while (iteratorFrame != null) + { + T newFrame = (T)iteratorFrame.Clone(); + if (_currentFrame == null) + { + _currentFrame = newFrame; + } + if (lastFrameInNewStack != null) + { + lastFrameInNewStack.Previous = newFrame; + } + lastFrameInNewStack = newFrame; + iteratorFrame = (T)iteratorFrame.Previous; + } + } + } + + //allocate a new frame as the new currentFrame; + private void Grow() + { + T lastFrame = _currentFrame; + _currentFrame = _creationDelegate(); + _currentFrame.Previous = lastFrame; + } + + public T CurrentFrame + { + get { return _currentFrame; } + } + + public T PreviousFrame + { + get { return (T)_currentFrame.Previous; } + } + + public T PreviousPreviousFrame + { + get { return (T)_currentFrame.Previous.Previous; } + } + + public T GetFrame(int depth) + { + T iteratorFrame = _currentFrame; + Debug.Assert(iteratorFrame != null); + while (iteratorFrame.Depth > depth) + { + iteratorFrame = (T)iteratorFrame.Previous; + } + return iteratorFrame; + } + + //Consumers of this stack call PushScope, and we'll either allocate a new frame + // or we'll grab one from our recycled linked list. + public void PushScope() + { + if (_recycledFrame == null) + { + Grow(); + } + else //use recycled frame + { + T lastFrame = _currentFrame; + _currentFrame = _recycledFrame; + _recycledFrame = (T)_recycledFrame.Previous; + _currentFrame.Previous = lastFrame; + } + _depth++; + Debug.Assert(CurrentFrame.Depth == Depth); + } + + //Consumers of this stack call PopScope, and we'll move the currentFrame from the main + // linked list to the recylced linked list and call .Reset + public void PopScope() + { + _depth--; + T frameToRecycle = _currentFrame; + _currentFrame = (T)_currentFrame.Previous; + frameToRecycle.Previous = _recycledFrame; + _recycledFrame = frameToRecycle; + frameToRecycle.Reset(); + Debug.Assert(CurrentFrame.Depth == Depth); + } + + public int Depth + { + get { return _depth; } + set { _depth = value; } + } + + //In case the stack needs to survive and you don't want to keep the recylced frames around. + public void Trim() + { + _recycledFrame = null; + } + + public string Frames + { + get + { + StringBuilder sb = new StringBuilder(); + T iteratorFrame = _currentFrame; + sb.AppendLine("Stack: " + (_currentFrame == null ? -1 : _currentFrame.Depth + 1).ToString(CultureInfo.InvariantCulture) + " frames"); + ShowFrame(sb, _currentFrame); + return sb.ToString(); + } + } + + private void ShowFrame(StringBuilder sb, T iteratorFrame) + { + if (iteratorFrame == null) + return; + if (iteratorFrame.Previous != null) + ShowFrame(sb, (T)iteratorFrame.Previous); + sb.AppendLine(" " + iteratorFrame.Depth + " " + iteratorFrame.ToString()); + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Context/XamlFrame.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Context/XamlFrame.cs new file mode 100644 index 00000000000..5d8cdde7779 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Context/XamlFrame.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; + +namespace MS.Internal.Xaml.Context +{ + abstract class XamlFrame + { + private int _depth; + private XamlFrame _previous; + + protected XamlFrame() + { + _depth = -1; + } + + // Copy constructor + protected XamlFrame(XamlFrame source) + { + _depth = source._depth; + } + + public virtual XamlFrame Clone() + { + // Clone should only be overridden for the classes that really need it + // ObjectWriterFrame overrides this so we can reuse the context for + // Templates. + throw new NotImplementedException(); + } + + // Reset the contents of the Frame so it can be reused in a stack without reallocating. + // Depth and previous do not change when we reuse the Frame. + public abstract void Reset(); + + public int Depth + { + get + { + Debug.Assert(_depth != -1, "Context Frame is uninitialized"); + return _depth; + } + } + + public XamlFrame Previous + { + get { return _previous; } + set + { + _previous = value; + _depth = (_previous == null) ? 0 : _previous._depth + 1; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Parser/SpecialBracketCharacters.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Parser/SpecialBracketCharacters.cs new file mode 100644 index 00000000000..a44db978d72 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Parser/SpecialBracketCharacters.cs @@ -0,0 +1,139 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// +// Description: Data model for the Bracket characters specified on a Markup Extension property. +// + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; + +namespace MS.Internal.Xaml.Parser +{ + /// + /// Class that provides helper functions for the parser/Xaml Reader + /// to process Bracket Characters specified on a Markup Extension Property + /// + internal class SpecialBracketCharacters : ISupportInitialize + { + private string _startChars; + private string _endChars; + private readonly static ISet _restrictedCharSet = new SortedSet((new char[] { '=', ',', '\'', '"', '{', '}', '\\' })); + private bool _initializing; + private StringBuilder _startCharactersStringBuilder; + private StringBuilder _endCharactersStringBuilder; + + internal SpecialBracketCharacters() + { + BeginInit(); + } + + internal SpecialBracketCharacters(IReadOnlyDictionary attributeList) + { + BeginInit(); + if (attributeList != null && attributeList.Count > 0) + { + Tokenize(attributeList); + } + } + + internal void AddBracketCharacters(char openingBracket, char closingBracket) + { + if (_initializing) + { + _startCharactersStringBuilder.Append(openingBracket); + _endCharactersStringBuilder.Append(closingBracket); + } + else + { + throw new InvalidOperationException(); + } + } + + private void Tokenize(IReadOnlyDictionary attributeList) + { + if (_initializing) + { + foreach (char openingBracket in attributeList.Keys) + { + char closingBracket = attributeList[openingBracket]; + string errorMessage = string.Empty; + if (IsValidBracketCharacter(openingBracket, closingBracket)) + { + _startCharactersStringBuilder.Append(openingBracket); + _endCharactersStringBuilder.Append(closingBracket); + } + } + } + } + + private bool IsValidBracketCharacter(char openingBracket, char closingBracket) + { + if (openingBracket == closingBracket) + { + throw new InvalidOperationException("Opening bracket character cannot be the same as closing bracket character."); + } + else if (char.IsLetterOrDigit(openingBracket) || char.IsLetterOrDigit(closingBracket) || char.IsWhiteSpace(openingBracket) || char.IsWhiteSpace(closingBracket)) + { + throw new InvalidOperationException("Bracket characters cannot be alpha-numeric or whitespace."); + } + else if (_restrictedCharSet.Contains(openingBracket) || _restrictedCharSet.Contains(closingBracket)) + { + throw new InvalidOperationException("Bracket characters cannot be one of the following: '=' , ',', '\'', '\"', '{ ', ' }', '\\'"); + } + else + { + return true; + } + } + + internal bool IsSpecialCharacter(char ch) + { + return _startChars.Contains(ch.ToString()) || _endChars.Contains(ch.ToString()); + } + + internal bool StartsEscapeSequence(char ch) + { + return _startChars.Contains(ch.ToString()); + } + + internal bool EndsEscapeSequence(char ch) + { + return _endChars.Contains(ch.ToString()); + } + + internal bool Match(char start, char end) + { + return _endChars.IndexOf(end.ToString()) == _startChars.IndexOf(start.ToString()); + } + + internal string StartBracketCharacters + { + get { return _startChars; } + } + + internal string EndBracketCharacters + { + get { return _endChars; } + } + + public void BeginInit() + { + _initializing = true; + _startCharactersStringBuilder = new StringBuilder(); + _endCharactersStringBuilder = new StringBuilder(); + } + + public void EndInit() + { + _startChars = _startCharactersStringBuilder.ToString(); + _endChars = _endCharactersStringBuilder.ToString(); + _initializing = false; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/BindUriHelper.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/BindUriHelper.cs new file mode 100644 index 00000000000..12600f95c83 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/BindUriHelper.cs @@ -0,0 +1,187 @@ +using System; +using System.IO; +using System.Net; // HttpWebRequest +using System.Net.Cache; // HttpRequestCachePolicy +using System.ComponentModel; +using System.Diagnostics; +using System.Globalization; +using System.Text; +using System.Windows.Navigation; // BaseUriHelper + +#if !PBTCOMPILER +using MS.Win32; +#endif + +using System.Security; +using System.Security.Permissions; +// The functionality in this class is shared across framework and core. The functionality in core +// is a subset of the functionality in framework, so rather than create a dependency from core to +// framework we have choses to duplicate this chunk of code. +#if PRESENTATION_CORE +namespace MS.Internal.PresentationCore +#elif PRESENTATIONFRAMEWORK +using MS.Internal.PresentationFramework; // SecurityHelper + +namespace MS.Internal.Utility +#elif PBTCOMPILER +using MS.Internal.PresentationBuildTasks // SecurityHelper + +namespace MS.Internal.Utility +#elif REACHFRAMEWORK +using MS.Internal.ReachFramework; // SecurityHelper + +namespace MS.Internal.Utility +#else +#error Class is being used from an unknown assembly. +#endif +{ + // + // Methods in this partial class are shared by PresentationFramework and PresentationBuildTasks. + // See also WpfWebRequestHelper. + // + internal static partial class BindUriHelper + { + private const int MAX_PATH_LENGTH = 2048 ; + private const int MAX_SCHEME_LENGTH = 32; + public const int MAX_URL_LENGTH = MAX_PATH_LENGTH + MAX_SCHEME_LENGTH + 3; /*=sizeof("://")*/ + + // + // Uri-toString does 3 things over the standard .toString() + // + // 1) We don't unescape special control characters. The default Uri.ToString() + // will unescape a character like ctrl-g, or ctrl-h so the actual char is emitted. + // However it's considered safer to emit the escaped version. + // + // 2) We truncate urls so that they are always <= MAX_URL_LENGTH + // + // This method should be called whenever you are taking a Uri + // and performing a p-invoke on it. + // + internal static string UriToString(Uri uri) + { + if (uri == null) + { + throw new ArgumentNullException("uri"); + } + + return new StringBuilder( + uri.GetComponents( + uri.IsAbsoluteUri ? UriComponents.AbsoluteUri : UriComponents.SerializationInfoString, + UriFormat.SafeUnescaped), + MAX_URL_LENGTH).ToString(); + } + +#if PRESENTATION_CORE || PRESENTATIONFRAMEWORK + // Base Uri. + /// + /// Critical: as it sets the baseUri + /// + static internal Uri BaseUri + { + get + { + return BaseUriHelper.BaseUri; + } + [SecurityCritical] + set + { + BaseUriHelper.BaseUri = BaseUriHelper.FixFileUri(value); + } + } + + static internal bool DoSchemeAndHostMatch(Uri first, Uri second) + { + // Check that both the scheme and the host match. + return (SecurityHelper.AreStringTypesEqual(first.Scheme, second.Scheme) && first.Host.Equals(second.Host) == true); + } + + static internal Uri GetResolvedUri(Uri baseUri, Uri orgUri) + { + Uri newUri; + + if (orgUri == null) + { + newUri = null; + } + else if (orgUri.IsAbsoluteUri == false) + { + // if the orgUri is an absolute Uri, don't need to resolve it again. + + Uri baseuri = (baseUri == null) ? BindUriHelper.BaseUri : baseUri; + +#if CF_Envelope_Activation_Enabled + bool isContainer = false ; + + // + // if the BaseUri starts with pack://application we know that we're not in a container. + // + // By deferring the registration of the container scheme - we avoid registering the ssres protocol. + // and enable less code that requires elevation. + // + // Note that when container moves to pack: ( PS 25616) - we won't need this check anyway. + // + + if ( // Check that the baseuri starts with pack://application:,,,/ + ! DoSchemeAndHostMatch(baseuri, BaseUriHelper.PackAppBaseUri)) + { + isContainer = String.Compare(baseuri.Scheme, CompoundFileUri.UriSchemeContainer, StringComparison.OrdinalIgnoreCase) == 0; + } + + Debug.Assert(baseuri.OriginalString == BaseUriHelper.FixFileUri(baseuri).OriginalString, "Base Uri is legacy file Uri and may not resolve relative uris correctly. This method should be updated"); + + // ToDo (younggk): PS# 25616 Once we move to PackUri, we don't need a special way + // of resolving Uri. We can use the regurlar one. + if (isContainer) + { + newUri = ResolveContainerUri(baseuri, orgUri); + } + else + { +#endif + newUri = new Uri(baseuri, orgUri); +#if CF_Envelope_Activation_Enabled + } +#endif + } + else + { + newUri = BaseUriHelper.FixFileUri(orgUri); + } + + return newUri; + } + + /// + /// Gets the referer to set as a header on the HTTP request. + /// We do not set the referer if we are navigating to a + /// differnet security zone or to a different Uri scheme. + /// + internal static string GetReferer(Uri destinationUri) + { + string referer = null; + + Uri sourceUri = MS.Internal.AppModel.SiteOfOriginContainer.BrowserSource; + if (sourceUri != null) + { + SecurityZone sourceZone = MS.Internal.AppModel.CustomCredentialPolicy.MapUrlToZone(sourceUri); + SecurityZone targetZone = MS.Internal.AppModel.CustomCredentialPolicy.MapUrlToZone(destinationUri); + + // We don't send any referer when crossing zone + if (sourceZone == targetZone) + { + // We don't send any referer when going cross-scheme + if (SecurityHelper.AreStringTypesEqual(sourceUri.Scheme, destinationUri.Scheme)) + { + // HTTPHeader requires the referer uri to be escaped. + referer = sourceUri.GetComponents(UriComponents.AbsoluteUri, UriFormat.UriEscaped); + } + } + } + + return referer; + } + + +#endif // PRESENTATION_CORE || PRESENTATIONFRAMEWORK + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalList.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalList.cs new file mode 100644 index 00000000000..d5d8d414569 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalList.cs @@ -0,0 +1,2344 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System; +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System.Windows; +using System.Diagnostics.CodeAnalysis; +#if SYSTEM_XAML +using System.Xaml; +#else +using MS.Internal.WindowsBase; +#endif + +//using MS.Internal.PresentationCore; +//using SR=MS.Internal.WindowsBase.SR; +//using SRID=MS.Internal.WindowsBase.SRID; + + // These classes implement a frugal storage model for lists of type . + // Performance measurements show that Avalon has many lists that contain + // a limited number of entries, and frequently zero or a single entry. + // Therefore these classes are structured to prefer a storage model that + // starts at zero, and employs a conservative growth strategy to minimize + // the steady state memory footprint. Also note that the list uses one + // fewer objects than ArrayList and List and does no allocations at all + // until an item is inserted into the list. + // + // The code is also structured to perform well from a CPU standpoint. Perf + // analysis shows that the reduced number of processor cache misses makes + // FrugalList faster than ArrayList or List, especially for lists of 6 + // or fewer items. Timing differ with the size of . + // + // FrugalList is appropriate for small lists or lists that grow slowly. + // Due to the slow growth, if you use it for a list with more than 6 initial + // entires is best to set the capacity of the list at construction time or + // soon after. If you must grow the list by a large amount, set the capacity + // or use Insert() method to force list growth to the final size. Choose + // your collections wisely and pay particular attention to the growth + // patterns and search methods. + + // FrugalList has all of the methods of the Ilist interface, but implements + // them as virtual methods of the class and not as Interface methods. This + // is to avoid the virtual stub dispatch CPU costs associated with Interfaces. + + // We suppress two FxCop warnings in this module because not all usages + // of FrugalList will instantiate all the storage classes and not all class instances + // will use every method. + // CA1811:AvoidUncalledPrivateCode + // CA1812:AvoidUninstantiatedInternalClasses + // + +#if SYSTEM_XAML +namespace System.Xaml.MS.Impl +#else +namespace MS.Utility +#endif +{ + // These classes implement a frugal storage model for lists of . + // Performance measurements show that many lists contain a single item. + // Therefore this list is structured to prefer a list that contains a single + // item, and does conservative growth to minimize the memory footprint. + + // This enum controls the growth to successively more complex storage models + internal enum FrugalListStoreState + { + Success, + SingleItemList, + ThreeItemList, + SixItemList, + Array + } + + abstract class FrugalListBase + { + /// + /// Number of entries in this store + /// + // Number of entries in this store + public int Count + { + get + { + return _count; + } + } + + // for use only by trusted callers - e.g. FrugalObjectList.Compacter + internal void TrustedSetCount(int newCount) + { + _count = newCount; + } + + /// + /// Capacity of this store + /// + public abstract int Capacity + { + get; + } + + // Increase size if needed, insert item into the store + public abstract FrugalListStoreState Add(T value); + + /// + /// Removes all values from the store + /// + public abstract void Clear(); + + /// + /// Returns true if the store contains the entry. + /// + public abstract bool Contains(T value); + + /// + /// Returns the index into the store that contains the item. + /// -1 is returned if the item is not in the store. + /// + public abstract int IndexOf(T value); + + /// + /// Insert item into the store at index, grows if needed + /// + public abstract void Insert(int index, T value); + + // Place item into the store at index + public abstract void SetAt(int index, T value); + + /// + /// Removes the item from the store. If the item was not + /// in the store false is returned. + /// + public abstract bool Remove(T value); + + /// + /// Removes the item from the store + /// + public abstract void RemoveAt(int index); + + /// + /// Return the item at index in the store + /// + public abstract T EntryAt(int index); + + /// + /// Promotes the values in the current store to the next larger + /// and more complex storage model. + /// + public abstract void Promote(FrugalListBase newList); + + /// + /// Returns the entries as an array + /// + public abstract T[] ToArray(); + + /// + /// Copies the entries to the given array starting at the + /// specified index + /// + public abstract void CopyTo(T[] array, int index); + + /// + /// Creates a shallow copy of the list + /// + public abstract object Clone(); + + // The number of items in the list. + protected int _count; + + #region Compacter + + public virtual Compacter NewCompacter(int newCount) + { + return new Compacter(this, newCount); + } + + // basic implementation - compacts in-place + internal class Compacter + { + public Compacter(FrugalListBase store, int newCount) + { + _store = store; + _newCount = newCount; + } + + public void Include(int start, int end) + { + Debug.Assert(start >= _previousEnd, "Arguments out of order during Compact"); + Debug.Assert(_validItemCount + end - start <= _newCount, "Too many items copied during Compact"); + + IncludeOverride(start, end); + + _previousEnd = end; + } + + protected virtual void IncludeOverride(int start, int end) + { + // item-by-item move + for (int i=start; i Finish() + { + // clear out vacated entries + T filler = default(T); + for (int i=_validItemCount, n=_store._count; i _store; + protected int _validItemCount; + protected int _previousEnd; + private int _newCount; + } + + #endregion Compacter + } + + /// + /// A simple class to handle a single item + /// + internal sealed class SingleItemList : FrugalListBase + { + // Capacity of this store + public override int Capacity + { + get + { + return SIZE; + } + } + + public override FrugalListStoreState Add(T value) + { + // If we don't have any entries or the existing entry is being overwritten, + // then we can use this store. Otherwise we have to promote. + if (0 == _count) + { + _loneEntry = value; + ++_count; + return FrugalListStoreState.Success; + } + else + { + // Entry already used, move to an ThreeItemList + return FrugalListStoreState.ThreeItemList; + } + } + + public override void Clear() + { + // Wipe out the info + _loneEntry = default(T); + _count = 0; + } + + public override bool Contains(T value) + { + return _loneEntry.Equals(value); + } + + public override int IndexOf(T value) + { + if (_loneEntry.Equals(value)) + { + return 0; + } + return -1; + } + + public override void Insert(int index, T value) + { + // Should only get here if count and index are 0 + if ((_count < SIZE) && (index < SIZE)) + { + _loneEntry = value; + ++_count; + return; + } + throw new ArgumentOutOfRangeException("index"); + } + + public override void SetAt(int index, T value) + { + // Overwrite item at index + _loneEntry = value; + } + + public override bool Remove(T value) + { + // Wipe out the info in the only entry if it matches the item. + if (_loneEntry.Equals(value)) + { + _loneEntry = default(T); + --_count; + return true; + } + + return false; + } + + public override void RemoveAt(int index) + { + // Wipe out the info at index + if (0 == index) + { + _loneEntry = default(T); + --_count; + } + else + { + throw new ArgumentOutOfRangeException("index"); + } + } + + public override T EntryAt(int index) + { + return _loneEntry; + } + + public override void Promote(FrugalListBase oldList) + { + if (SIZE == oldList.Count) + { + SetCount(SIZE); + SetAt(0, oldList.EntryAt(0)); + } + else + { + // this list is smaller than oldList + throw new ArgumentException(SR.Get(SRID.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), "oldList"); + } + } + + // Class specific implementation to avoid virtual method calls and additional logic + public void Promote(SingleItemList oldList) + { + SetCount(oldList.Count); + SetAt(0, oldList.EntryAt(0)); + } + + public override T[] ToArray() + { + T[] array = new T[1]; + array[0] = _loneEntry; + return array; + } + + public override void CopyTo(T[] array, int index) + { + array[index] = _loneEntry; + } + + public override object Clone() + { + SingleItemList newList = new SingleItemList(); + newList.Promote(this); + return newList; + } + + private void SetCount(int value) + { + if ((value >= 0) && (value <= SIZE)) + { + _count = value; + } + else + { + throw new ArgumentOutOfRangeException("value"); + } + } + + private const int SIZE = 1; + + private T _loneEntry; + } + + + /// + /// A simple class to handle a list with 3 items. Perf analysis showed + /// that this yielded better memory locality and perf than an object and an array. + /// + internal sealed class ThreeItemList : FrugalListBase + { + // Capacity of this store + public override int Capacity + { + get + { + return SIZE; + } + } + + public override FrugalListStoreState Add(T value) + { + switch (_count) + { + case 0: + _entry0 = value; + break; + + case 1: + _entry1 = value; + break; + + case 2: + _entry2 = value; + break; + + default: + // We have to promote + return FrugalListStoreState.SixItemList; + } + ++_count; + return FrugalListStoreState.Success; + } + + public override void Clear() + { + // Wipe out the info. + _entry0 = default(T); + _entry1 = default(T); + _entry2 = default(T); + _count = 0; + } + + public override bool Contains(T value) + { + return (-1 != IndexOf(value)); + } + + public override int IndexOf(T value) + { + if (_entry0.Equals(value)) + { + return 0; + } + if (_count > 1) + { + if (_entry1.Equals(value)) + { + return 1; + } + if ((3 == _count) && (_entry2.Equals(value))) + { + return 2; + } + } + return -1; + } + + public override void Insert(int index, T value) + { + // Should only get here if count < SIZE + if (_count < SIZE) + { + switch (index) + { + case 0: + _entry2 = _entry1; + _entry1 = _entry0; + _entry0 = value; + break; + + case 1: + _entry2 = _entry1; + _entry1 = value; + break; + + case 2: + _entry2 = value; + break; + + default: + throw new ArgumentOutOfRangeException("index"); + } + ++_count; + return; + } + throw new ArgumentOutOfRangeException("index"); + } + + public override void SetAt(int index, T value) + { + // Overwrite item at index + switch (index) + { + case 0: + _entry0 = value; + break; + + case 1: + _entry1 = value; + break; + + case 2: + _entry2 = value; + break; + + default: + throw new ArgumentOutOfRangeException("index"); + } + } + + public override bool Remove(T value) + { + // If the item matches an existing entry, wipe out the last + // entry and move all the other entries up. Because we only + // have three entries we can just unravel all the cases. + if (_entry0.Equals(value)) + { + RemoveAt(0); + return true; + } + else if ( _count > 1) + { + if (_entry1.Equals(value)) + { + RemoveAt(1); + return true; + } + else if ((3 == _count) && (_entry2.Equals(value))) + { + RemoveAt(2); + return true; + } + } + return false; + } + + public override void RemoveAt(int index) + { + // Remove entry at index, wipe out the last entry and move + // all the other entries up. Because we only have three + // entries we can just unravel all the cases. + switch (index) + { + case 0: + _entry0 = _entry1; + _entry1 = _entry2; + break; + + case 1: + _entry1 = _entry2; + break; + + case 2: + break; + + default: + throw new ArgumentOutOfRangeException("index"); + } + _entry2 = default(T); + --_count; + } + + public override T EntryAt(int index) + { + switch (index) + { + case 0: + return _entry0; + + case 1: + return _entry1; + + case 2: + return _entry2; + + default: + throw new ArgumentOutOfRangeException("index"); + } + } + + public override void Promote(FrugalListBase oldList) + { + int oldCount = oldList.Count; + if (SIZE >= oldCount) + { + SetCount(oldList.Count); + + switch (oldCount) + { + case 3: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + break; + + case 2: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + break; + + case 1: + SetAt(0, oldList.EntryAt(0)); + break; + + case 0: + break; + + default: + throw new ArgumentOutOfRangeException("oldList"); + } + } + else + { + // this list is smaller than oldList + throw new ArgumentException(SR.Get(SRID.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), "oldList"); + } + } + + // Class specific implementation to avoid virtual method calls and additional logic + public void Promote(SingleItemList oldList) + { + SetCount(oldList.Count); + SetAt(0, oldList.EntryAt(0)); + } + + // Class specific implementation to avoid virtual method calls and additional logic + public void Promote(ThreeItemList oldList) + { + int oldCount = oldList.Count; + SetCount(oldList.Count); + + switch (oldCount) + { + case 3: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + break; + + case 2: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + break; + + case 1: + SetAt(0, oldList.EntryAt(0)); + break; + + case 0: + break; + + default: + throw new ArgumentOutOfRangeException("oldList"); + } + } + + public override T[] ToArray() + { + T[] array = new T[_count]; + + array[0] = _entry0; + if (_count >= 2) + { + array[1] = _entry1; + if (_count == 3) + { + array[2] = _entry2; + } + } + return array; + } + + public override void CopyTo(T[] array, int index) + { + array[index] = _entry0; + if (_count >= 2) + { + array[index+1] = _entry1; + if (_count == 3) + { + array[index+2] = _entry2; + } + } + } + + public override object Clone() + { + ThreeItemList newList = new ThreeItemList(); + newList.Promote(this); + return newList; + } + + private void SetCount(int value) + { + if ((value >= 0) && (value <= SIZE)) + { + _count = value; + } + else + { + throw new ArgumentOutOfRangeException("value"); + } + } + + private const int SIZE = 3; + + private T _entry0; + private T _entry1; + private T _entry2; + } + + /// + /// A simple class to handle a list with 6 items. + /// + internal sealed class SixItemList : FrugalListBase + { + // Capacity of this store + public override int Capacity + { + get + { + return SIZE; + } + } + + public override FrugalListStoreState Add(T value) + { + switch (_count) + { + case 0: + _entry0 = value; + break; + + case 1: + _entry1 = value; + break; + + case 2: + _entry2 = value; + break; + + case 3: + _entry3 = value; + break; + + case 4: + _entry4 = value; + break; + + case 5: + _entry5 = value; + break; + + default: + // We have to promote + return FrugalListStoreState.Array; + } + ++_count; + return FrugalListStoreState.Success; + } + + public override void Clear() + { + // Wipe out the info. + _entry0 = default(T); + _entry1 = default(T); + _entry2 = default(T); + _entry3 = default(T); + _entry4 = default(T); + _entry5 = default(T); + _count = 0; + } + + public override bool Contains(T value) + { + return (-1 != IndexOf(value)); + } + + public override int IndexOf(T value) + { + if (_entry0.Equals(value)) + { + return 0; + } + if (_count > 1) + { + if (_entry1.Equals(value)) + { + return 1; + } + if (_count > 2) + { + if (_entry2.Equals(value)) + { + return 2; + } + if (_count > 3) + { + if (_entry3.Equals(value)) + { + return 3; + } + if (_count > 4) + { + if (_entry4.Equals(value)) + { + return 4; + } + if ((6 == _count) && (_entry5.Equals(value))) + { + return 5; + } + } + } + } + } + return -1; + } + + public override void Insert(int index, T value) + { + // Should only get here if count is less than SIZE + if (_count < SIZE) + { + switch (index) + { + case 0: + _entry5 = _entry4; + _entry4 = _entry3; + _entry3 = _entry2; + _entry2 = _entry1; + _entry1 = _entry0; + _entry0 = value; + break; + + case 1: + _entry5 = _entry4; + _entry4 = _entry3; + _entry3 = _entry2; + _entry2 = _entry1; + _entry1 = value; + break; + + case 2: + _entry5 = _entry4; + _entry4 = _entry3; + _entry3 = _entry2; + _entry2 = value; + break; + + case 3: + _entry5 = _entry4; + _entry4 = _entry3; + _entry3 = value; + break; + + case 4: + _entry5 = _entry4; + _entry4 = value; + break; + + case 5: + _entry5 = value; + break; + + default: + throw new ArgumentOutOfRangeException("index"); + } + ++_count; + return; + } + throw new ArgumentOutOfRangeException("index"); + } + + public override void SetAt(int index, T value) + { + // Overwrite item at index + switch (index) + { + case 0: + _entry0 = value; + break; + + case 1: + _entry1 = value; + break; + + case 2: + _entry2 = value; + break; + + case 3: + _entry3 = value; + break; + + case 4: + _entry4 = value; + break; + + case 5: + _entry5 = value; + break; + + default: + throw new ArgumentOutOfRangeException("index"); + } + } + + public override bool Remove(T value) + { + // If the item matches an existing entry, wipe out the last + // entry and move all the other entries up. Because we only + // have six entries we can just unravel all the cases. + if (_entry0.Equals(value)) + { + RemoveAt(0); + return true; + } + else if (_count > 1) + { + if (_entry1.Equals(value)) + { + RemoveAt(1); + return true; + } + else if (_count > 2) + { + if (_entry2.Equals(value)) + { + RemoveAt(2); + return true; + } + else if (_count > 3) + { + if (_entry3.Equals(value)) + { + RemoveAt(3); + return true; + } + else if (_count > 4) + { + if (_entry4.Equals(value)) + { + RemoveAt(4); + return true; + } + else if ((6 == _count) && (_entry5.Equals(value))) + { + RemoveAt(5); + return true; + } + } + } + } + } + + return false; + } + + public override void RemoveAt(int index) + { + // Remove entry at index, wipe out the last entry and move + // all the other entries up. Because we only have six + // entries we can just unravel all the cases. + switch (index) + { + case 0: + _entry0 = _entry1; + _entry1 = _entry2; + _entry2 = _entry3; + _entry3 = _entry4; + _entry4 = _entry5; + break; + + case 1: + _entry1 = _entry2; + _entry2 = _entry3; + _entry3 = _entry4; + _entry4 = _entry5; + break; + + case 2: + _entry2 = _entry3; + _entry3 = _entry4; + _entry4 = _entry5; + break; + + case 3: + _entry3 = _entry4; + _entry4 = _entry5; + break; + + case 4: + _entry4 = _entry5; + break; + + case 5: + break; + + default: + throw new ArgumentOutOfRangeException("index"); + } + _entry5 = default(T); + --_count; + } + + public override T EntryAt(int index) + { + switch (index) + { + case 0: + return _entry0; + + case 1: + return _entry1; + + case 2: + return _entry2; + + case 3: + return _entry3; + + case 4: + return _entry4; + + case 5: + return _entry5; + + default: + throw new ArgumentOutOfRangeException("index"); + } + } + + public override void Promote(FrugalListBase oldList) + { + int oldCount = oldList.Count; + if (SIZE >= oldCount) + { + SetCount(oldList.Count); + + switch (oldCount) + { + case 6: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + SetAt(3, oldList.EntryAt(3)); + SetAt(4, oldList.EntryAt(4)); + SetAt(5, oldList.EntryAt(5)); + break; + + case 5: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + SetAt(3, oldList.EntryAt(3)); + SetAt(4, oldList.EntryAt(4)); + break; + + case 4: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + SetAt(3, oldList.EntryAt(3)); + break; + + case 3: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + break; + + case 2: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + break; + + case 1: + SetAt(0, oldList.EntryAt(0)); + break; + + case 0: + break; + + default: + throw new ArgumentOutOfRangeException("oldList"); + } + } + else + { + // this list is smaller than oldList + throw new ArgumentException(SR.Get(SRID.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), "oldList"); + } + } + + // Class specific implementation to avoid virtual method calls and additional logic + public void Promote(ThreeItemList oldList) + { + int oldCount = oldList.Count; + if (SIZE <= oldCount) + { + SetCount(oldList.Count); + + switch (oldCount) + { + case 3: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + break; + + case 2: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + break; + + case 1: + SetAt(0, oldList.EntryAt(0)); + break; + + case 0: + break; + + default: + throw new ArgumentOutOfRangeException("oldList"); + } + } + else + { + // this list is smaller than oldList + throw new ArgumentException(SR.Get(SRID.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), "oldList"); + } + } + + // Class specific implementation to avoid virtual method calls and additional logic + public void Promote(SixItemList oldList) + { + int oldCount = oldList.Count; + SetCount(oldList.Count); + + switch (oldCount) + { + case 6: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + SetAt(3, oldList.EntryAt(3)); + SetAt(4, oldList.EntryAt(4)); + SetAt(5, oldList.EntryAt(5)); + break; + + case 5: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + SetAt(3, oldList.EntryAt(3)); + SetAt(4, oldList.EntryAt(4)); + break; + + case 4: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + SetAt(3, oldList.EntryAt(3)); + break; + + case 3: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + break; + + case 2: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + break; + + case 1: + SetAt(0, oldList.EntryAt(0)); + break; + + case 0: + break; + + default: + throw new ArgumentOutOfRangeException("oldList"); + } + } + + public override T[] ToArray() + { + T[] array = new T[_count]; + + if (_count >= 1) + { + array[0] = _entry0; + if (_count >= 2) + { + array[1] = _entry1; + if (_count >= 3) + { + array[2] = _entry2; + if (_count >= 4) + { + array[3] = _entry3; + if (_count >= 5) + { + array[4] = _entry4; + if (_count == 6) + { + array[5] = _entry5; + } + } + } + } + } + } + return array; + } + + public override void CopyTo(T[] array, int index) + { + if (_count >= 1) + { + array[index] = _entry0; + if (_count >= 2) + { + array[index+1] = _entry1; + if (_count >= 3) + { + array[index+2] = _entry2; + if (_count >= 4) + { + array[index+3] = _entry3; + if (_count >= 5) + { + array[index+4] = _entry4; + if (_count == 6) + { + array[index+5] = _entry5; + } + } + } + } + } + } + } + + public override object Clone() + { + SixItemList newList = new SixItemList(); + newList.Promote(this); + return newList; + } + + private void SetCount(int value) + { + if ((value >= 0) && (value <= SIZE)) + { + _count = value; + } + else + { + throw new ArgumentOutOfRangeException("value"); + } + } + + private const int SIZE = 6; + + private T _entry0; + private T _entry1; + private T _entry2; + private T _entry3; + private T _entry4; + private T _entry5; + } + + /// + /// A simple class to handle an array of 7 or more items. It is unsorted and uses + /// a linear search. + /// + internal sealed class ArrayItemList : FrugalListBase + { + public ArrayItemList() + { + } + + public ArrayItemList(int size) + { + // Make size a multiple of GROWTH + size += (GROWTH - 1); + size -= (size % GROWTH); + _entries = new T[size]; + } + + public ArrayItemList(ICollection collection) + { + if (collection != null) + { + _count = collection.Count; + _entries = new T[_count]; + collection.CopyTo(_entries, 0); + } + } + + public ArrayItemList(ICollection collection) + { + if (collection != null) + { + _count = collection.Count; + _entries = new T[_count]; + collection.CopyTo(_entries, 0); + } + } + + // Capacity of this store + public override int Capacity + { + get + { + if (_entries != null) + { + return _entries.Length; + } + return 0; + } + } + + public override FrugalListStoreState Add(T value) + { + // If we don't have any entries or the existing entry is being overwritten, + // then we can use this store. Otherwise we have to promote. + if ((null != _entries) && (_count < _entries.Length)) + { + _entries[_count] = value; + ++_count; + } + else + { + if (null != _entries) + { + int size = _entries.Length; + + // Grow the list slowly while it is small but + // faster once it reaches the LARGEGROWTH size + if (size < LARGEGROWTH) + { + size += GROWTH; + } + else + { + size += size >> 2; + } + + T[] destEntries = new T[size]; + + // Copy old array + Array.Copy(_entries, 0, destEntries, 0, _entries.Length); + _entries = destEntries; + } + else + { + _entries = new T[MINSIZE]; + } + + // Insert into new array + _entries[_count] = value; + ++_count; + } + return FrugalListStoreState.Success; + } + + public override void Clear() + { + // Wipe out the info. + for (int i = 0; i < _count; ++i) + { + _entries[i] = default(T); + } + _count = 0; + } + + public override bool Contains(T value) + { + return (-1 != IndexOf(value)); + } + + public override int IndexOf(T value) + { + for (int index = 0; index < _count; ++index) + { + if (_entries[index].Equals(value)) + { + return index; + } + } + return -1; + } + + public override void Insert(int index, T value) + { + if ((null != _entries) && (_count < _entries.Length)) + { + // Move down the required number of items + Array.Copy(_entries, index, _entries, index + 1, _count - index); + + // Put in the new item at the specified index + _entries[index] = value; + ++_count; + return; + } + throw new ArgumentOutOfRangeException("index"); + } + + public override void SetAt(int index, T value) + { + // Overwrite item at index + _entries[index] = value; + } + + public override bool Remove(T value) + { + for (int index = 0; index < _count; ++index) + { + if (_entries[index].Equals(value)) + { + RemoveAt(index); + return true; + } + } + + return false; + } + + public override void RemoveAt(int index) + { + // Shift entries down + int numToCopy = (_count - index) - 1; + if (numToCopy > 0) + { + Array.Copy(_entries, index + 1, _entries, index, numToCopy); + } + + // Wipe out the last entry + _entries[_count - 1] = default(T); + --_count; + return; + } + + public override T EntryAt(int index) + { + return _entries[index]; + } + + public override void Promote(FrugalListBase oldList) + { + for (int index = 0; index < oldList.Count; ++index) + { + if (FrugalListStoreState.Success == Add(oldList.EntryAt(index))) + { + continue; + } + // this list is smaller than oldList + throw new ArgumentException(SR.Get(SRID.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), "oldList"); + } + } + + // Class specific implementation to avoid virtual method calls and additional logic + public void Promote(SixItemList oldList) + { + int oldCount = oldList.Count; + SetCount(oldList.Count); + + switch (oldCount) + { + case 6: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + SetAt(3, oldList.EntryAt(3)); + SetAt(4, oldList.EntryAt(4)); + SetAt(5, oldList.EntryAt(5)); + break; + + case 5: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + SetAt(3, oldList.EntryAt(3)); + SetAt(4, oldList.EntryAt(4)); + break; + + case 4: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + SetAt(3, oldList.EntryAt(3)); + break; + + case 3: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + SetAt(2, oldList.EntryAt(2)); + break; + + case 2: + SetAt(0, oldList.EntryAt(0)); + SetAt(1, oldList.EntryAt(1)); + break; + + case 1: + SetAt(0, oldList.EntryAt(0)); + break; + + case 0: + break; + + default: + throw new ArgumentOutOfRangeException("oldList"); + } + } + + // Class specific implementation to avoid virtual method calls and additional logic + public void Promote(ArrayItemList oldList) + { + int oldCount = oldList.Count; + if (_entries.Length >= oldCount) + { + SetCount(oldList.Count); + + for (int index = 0; index < oldCount; ++index) + { + SetAt(index, oldList.EntryAt(index)); + } + } + else + { + // this list is smaller than oldList + throw new ArgumentException(SR.Get(SRID.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), "oldList"); + } + } + + public override T[] ToArray() + { + T[] array = new T[_count]; + + for (int i = 0; i < _count; ++i) + { + array[i] = _entries[i]; + } + return array; + } + + public override void CopyTo(T[] array, int index) + { + for (int i = 0; i < _count; ++i) + { + array[index+i] = _entries[i]; + } + } + + public override object Clone() + { + ArrayItemList newList = new ArrayItemList(this.Capacity); + newList.Promote(this); + return newList; + } + + private void SetCount(int value) + { + if ((value >= 0) && (value <= _entries.Length)) + { + _count = value; + } + else + { + throw new ArgumentOutOfRangeException("value"); + } + } + + // MINSIZE and GROWTH chosen to minimize memory footprint + private const int MINSIZE = 9; + private const int GROWTH = 3; + private const int LARGEGROWTH = 18; + + private T[] _entries; + + #region Compacter + + public override Compacter NewCompacter(int newCount) + { + return new ArrayCompacter(this, newCount); + } + + // array-based implementation - compacts in-place or into a new array + internal class ArrayCompacter : FrugalListBase.Compacter + { + public ArrayCompacter(ArrayItemList store, int newCount) + : base(store, newCount) + { + _sourceArray = store._entries; + + // compute capacity for target array + // the first term agrees with AIL.Add, which grows by 5/4 + int newCapacity = Math.Max(newCount + (newCount >> 2), MINSIZE); + + if (newCapacity + (newCapacity >> 2) >= _sourceArray.Length) + { + // if there's not much space to be reclaimed, compact in place + _targetStore = store; + } + else + { + // otherwise, compact into a smaller array + _targetStore = new ArrayItemList(newCapacity); + } + + _targetArray = _targetStore._entries; + } + + protected override void IncludeOverride(int start, int end) + { + // bulk move + int size = end - start; + Array.Copy(_sourceArray, start, _targetArray, _validItemCount, size); + _validItemCount += size; + + /* The following code is necessary in the general case, to avoid + * aliased entries in the old array. But the only user of Compacter + * is DependentList, where aliased entries are not a problem - they'll + * just get GC'd along with the old array. + + // when not compacting in place, clear out entries in the source + if (_targetArray != _sourceArray) + { + T filler = default(T); + for (int i=_previousEnd; i Finish() + { + // clear out vacated entries in the source + T filler = default(T); + if (_sourceArray == _targetArray) + { + // in-place array source + for (int i=_validItemCount, n=_store.Count; i _targetStore; + T[] _sourceArray; + T[] _targetArray; + } + + #endregion Compacter + } + + // Use FrugalObjectList when more than one reference to the list is needed. + // The "object" in FrugalObjectLIst refers to the list itself, not what the list contains. + +#if !SYSTEM_XAML + [FriendAccessAllowed] // Built into Core, also used by Framework. +#endif + internal class FrugalObjectList + { + public FrugalObjectList() + { + } + + public FrugalObjectList(int size) + { + Capacity = size; + } + + public int Capacity + { + get + { + if (null != _listStore) + { + return _listStore.Capacity; + } + return 0; + } + set + { + int capacity = 0; + if (null != _listStore) + { + capacity = _listStore.Capacity; + } + if (capacity < value) + { + // Need to move to a more complex storage + FrugalListBase newStore; + + if (value == 1) + { + newStore = new SingleItemList(); + } + else if (value <= 3) + { + newStore = new ThreeItemList(); + } + else if (value <= 6) + { + newStore = new SixItemList(); + } + else + { + newStore = new ArrayItemList(value); + } + + if (null != _listStore) + { + // Move entries in the old store to the new one + newStore.Promote(_listStore); + } + + _listStore = newStore; + } + } + } + + public int Count + { + get + { + if (null != _listStore) + { + return _listStore.Count; + } + return 0; + } + } + + + public T this[int index] + { + get + { + // If no entry, default(T) is returned + if ((null != _listStore) && ((index < _listStore.Count) && (index >= 0))) + { + return _listStore.EntryAt(index); + } + throw new ArgumentOutOfRangeException("index"); + } + + set + { + // Ensure write success + if ((null != _listStore) && ((index < _listStore.Count) && (index >= 0))) + { + _listStore.SetAt(index, value); + return; + } + throw new ArgumentOutOfRangeException("index"); + } + } + + public int Add(T value) + { + if (null != _listStore) + { + // This is done because forward branches + // default prediction is not to be taken + // making this a CPU win because Add is + // a common operation. + } + else + { + _listStore = new SingleItemList(); + } + + FrugalListStoreState myState = _listStore.Add(value); + if (FrugalListStoreState.Success == myState) + { + } + else + { + // Need to move to a more complex storage + // Allocate the store, promote, and add using the derived classes + // to avoid virtual method calls + + if (FrugalListStoreState.ThreeItemList == myState) + { + ThreeItemList newStore = new ThreeItemList(); + + // Extract the values from the old store and insert them into the new store + newStore.Promote(_listStore); + + // Insert the new item + newStore.Add(value); + _listStore = newStore; + } + else if (FrugalListStoreState.SixItemList == myState) + { + SixItemList newStore = new SixItemList(); + + // Extract the values from the old store and insert them into the new store + newStore.Promote(_listStore); + _listStore = newStore; + + // Insert the new item + newStore.Add(value); + _listStore = newStore; + } + else if (FrugalListStoreState.Array == myState) + { + ArrayItemList newStore = new ArrayItemList(_listStore.Count + 1); + + // Extract the values from the old store and insert them into the new store + newStore.Promote(_listStore); + _listStore = newStore; + + // Insert the new item + newStore.Add(value); + _listStore = newStore; + } + else + { + throw new InvalidOperationException(SR.Get(SRID.FrugalList_CannotPromoteBeyondArray)); + } + } + return _listStore.Count - 1; + } + + public void Clear() + { + if (null != _listStore) + { + _listStore.Clear(); + } + } + + public bool Contains(T value) + { + if ((null != _listStore) && (_listStore.Count > 0)) + { + return _listStore.Contains(value); + } + return false; + } + + public int IndexOf(T value) + { + if ((null != _listStore) && (_listStore.Count > 0)) + { + return _listStore.IndexOf(value); + } + return -1; + } + + public void Insert(int index, T value) + { + if ((index == 0) || ((null != _listStore) && ((index <= _listStore.Count) && (index >= 0)))) + { + // Make sure we have a place to put the item + int minCapacity = 1; + + if ((null != _listStore) && (_listStore.Count == _listStore.Capacity)) + { + // Store is full + minCapacity = Capacity + 1; + } + + // Make the Capacity at *least* this big + Capacity = minCapacity; + + _listStore.Insert(index, value); + return; + } + throw new ArgumentOutOfRangeException("index"); + } + + public bool Remove(T value) + { + if ((null != _listStore) && (_listStore.Count > 0)) + { + return _listStore.Remove(value); + } + return false; + } + + public void RemoveAt(int index) + { + if ((null != _listStore) && ((index < _listStore.Count) && (index >= 0))) + { + _listStore.RemoveAt(index); + return; + } + throw new ArgumentOutOfRangeException("index"); + } + + public void EnsureIndex(int index) + { + if (index >= 0) + { + int delta = (index + 1) - Count; + if (delta > 0) + { + // Grow the store + Capacity = index + 1; + + T filler = default(T); + + // Insert filler structs or objects + for (int i = 0; i < delta; ++i) + { + _listStore.Add(filler); + } + } + return; + } + throw new ArgumentOutOfRangeException("index"); + } + + public T[] ToArray() + { + if ((null != _listStore) && (_listStore.Count > 0)) + { + return _listStore.ToArray(); + } + return null; + } + + public void CopyTo(T[] array, int index) + { + if ((null != _listStore) && (_listStore.Count > 0)) + { + _listStore.CopyTo(array, index); + } + } + + public FrugalObjectList Clone() + { + FrugalObjectList myClone = new FrugalObjectList(); + + if (null != _listStore) + { + myClone._listStore = (FrugalListBase)_listStore.Clone(); + } + + return myClone; + } + + internal FrugalListBase _listStore; + + #region Compacter + // helper class - compacts the valid entries, while removing the invalid ones. + // Usage: + // Compacter compacter = new Compacter(this, newCount); + // compacter.Include(start, end); // repeat as necessary + // compacter.Finish(); + // newCount is the expected number of valid entries - used to help choose + // a target array of appropriate capacity + // Include(start, end) moves the entries in positions start, ..., end-1 toward + // the beginning, appending to the end of the "valid" area. Successive calls + // must be monotonic - i.e. the next 'start' must be >= the previous 'end'. + // Also, the sum of the block sizes (end-start) cannot exceed newCount. + // Finish() puts the provisional target array into permanent use. + + protected class Compacter + { + public Compacter(FrugalObjectList list, int newCount) + { + _list = list; + + FrugalListBase store = _list._listStore; + _storeCompacter = (store != null) ? store.NewCompacter(newCount) : null; + } + + public void Include(int start, int end) + { + _storeCompacter.Include(start, end); + } + + public void Finish() + { + if (_storeCompacter != null) + { + _list._listStore = _storeCompacter.Finish(); + } + } + + FrugalObjectList _list; + FrugalListBase.Compacter _storeCompacter; + } + #endregion Compacter + } + + // Use FrugalStructList when only one reference to the list is needed. + // The "struct" in FrugalStructList refers to the list itself, not what the list contains. +#if !SYSTEM_XAML + [FriendAccessAllowed] // Built into Core, also used by Framework. +#endif + internal struct FrugalStructList + { + public FrugalStructList(int size) + { + _listStore = null; + Capacity = size; + } + + public FrugalStructList(ICollection collection) + { + if (collection.Count > 6) + { + _listStore = new ArrayItemList(collection); + } + else + { + _listStore = null; + Capacity = collection.Count; + foreach (T item in collection) + { + Add(item); + } + } + } + + public FrugalStructList(ICollection collection) + { + if (collection.Count > 6) + { + _listStore = new ArrayItemList(collection); + } + else + { + _listStore = null; + Capacity = collection.Count; + foreach (T item in collection) + { + Add(item); + } + } + } + + public int Capacity + { + get + { + if (null != _listStore) + { + return _listStore.Capacity; + } + return 0; + } + set + { + int capacity = 0; + if (null != _listStore) + { + capacity = _listStore.Capacity; + } + if (capacity < value) + { + // Need to move to a more complex storage + FrugalListBase newStore; + + if (value == 1) + { + newStore = new SingleItemList(); + } + else if (value <= 3) + { + newStore = new ThreeItemList(); + } + else if (value <= 6) + { + newStore = new SixItemList(); + } + else + { + newStore = new ArrayItemList(value); + } + + if (null != _listStore) + { + // Move entries in the old store to the new one + newStore.Promote(_listStore); + } + + _listStore = newStore; + } + } + } + + public int Count + { + get + { + if (null != _listStore) + { + return _listStore.Count; + } + return 0; + } + } + + + public T this[int index] + { + get + { + // If no entry, default(T) is returned + if ((null != _listStore) && ((index < _listStore.Count) && (index >= 0))) + { + return _listStore.EntryAt(index); + } + throw new ArgumentOutOfRangeException("index"); + } + + set + { + // Ensure write success + if ((null != _listStore) && ((index < _listStore.Count) && (index >= 0))) + { + _listStore.SetAt(index, value); + return; + } + throw new ArgumentOutOfRangeException("index"); + } + } + + public int Add(T value) + { + if (null != _listStore) + { + // This is done because forward branches + // default prediction is not to be taken + // making this a CPU win because Add is + // a common operation. + } + else + { + _listStore = new SingleItemList(); + } + + FrugalListStoreState myState = _listStore.Add(value); + if (FrugalListStoreState.Success == myState) + { + } + else + { + // Need to move to a more complex storage + // Allocate the store, promote, and add using the derived classes + // to avoid virtual method calls + + if (FrugalListStoreState.ThreeItemList == myState) + { + ThreeItemList newStore = new ThreeItemList(); + + // Extract the values from the old store and insert them into the new store + newStore.Promote(_listStore); + + // Insert the new item + newStore.Add(value); + _listStore = newStore; + } + else if (FrugalListStoreState.SixItemList == myState) + { + SixItemList newStore = new SixItemList(); + + // Extract the values from the old store and insert them into the new store + newStore.Promote(_listStore); + _listStore = newStore; + + // Insert the new item + newStore.Add(value); + _listStore = newStore; + } + else if (FrugalListStoreState.Array == myState) + { + ArrayItemList newStore = new ArrayItemList(_listStore.Count + 1); + + // Extract the values from the old store and insert them into the new store + newStore.Promote(_listStore); + _listStore = newStore; + + // Insert the new item + newStore.Add(value); + _listStore = newStore; + } + else + { + throw new InvalidOperationException(SR.Get(SRID.FrugalList_CannotPromoteBeyondArray)); + } + } + return _listStore.Count - 1; + } + + public void Clear() + { + if (null != _listStore) + { + _listStore.Clear(); + } + } + + public bool Contains(T value) + { + if ((null != _listStore) && (_listStore.Count > 0)) + { + return _listStore.Contains(value); + } + return false; + } + + public int IndexOf(T value) + { + if ((null != _listStore) && (_listStore.Count > 0)) + { + return _listStore.IndexOf(value); + } + return -1; + } + + public void Insert(int index, T value) + { + if ((index == 0) || ((null != _listStore) && ((index <= _listStore.Count) && (index >= 0)))) + { + // Make sure we have a place to put the item + int minCapacity = 1; + + if ((null != _listStore) && (_listStore.Count == _listStore.Capacity)) + { + // Store is full + minCapacity = Capacity + 1; + } + + // Make the Capacity at *least* this big + Capacity = minCapacity; + + _listStore.Insert(index, value); + return; + } + throw new ArgumentOutOfRangeException("index"); + } + + public bool Remove(T value) + { + if ((null != _listStore) && (_listStore.Count > 0)) + { + return _listStore.Remove(value); + } + return false; + } + + public void RemoveAt(int index) + { + if ((null != _listStore) && ((index < _listStore.Count) && (index >= 0))) + { + _listStore.RemoveAt(index); + return; + } + throw new ArgumentOutOfRangeException("index"); + } + + public void EnsureIndex(int index) + { + if (index >= 0) + { + int delta = (index + 1) - Count; + if (delta > 0) + { + // Grow the store + Capacity = index + 1; + + T filler = default(T); + + // Insert filler structs or objects + for (int i = 0; i < delta; ++i) + { + _listStore.Add(filler); + } + } + return; + } + throw new ArgumentOutOfRangeException("index"); + } + + public T[] ToArray() + { + if ((null != _listStore) && (_listStore.Count > 0)) + { + return _listStore.ToArray(); + } + return null; + } + + public void CopyTo(T[] array, int index) + { + if ((null != _listStore) && (_listStore.Count > 0)) + { + _listStore.CopyTo(array, index); + } + } + + public FrugalStructList Clone() + { + FrugalStructList myClone = new FrugalStructList(); + + if (null != _listStore) + { + myClone._listStore = (FrugalListBase)_listStore.Clone(); + } + + return myClone; + } + + internal FrugalListBase _listStore; + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalMap.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalMap.cs new file mode 100644 index 00000000000..e66234bb999 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalMap.cs @@ -0,0 +1,2184 @@ +//--------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All rights reserved. +// +//--------------------------------------------------------------------------- + +using System; +using System.Diagnostics; +using System.Collections; +using System.Windows; + +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif DRT + using MS.Internal.Drt; +#else +#error Attempt to use FriendAccessAllowedAttribute from an unknown assembly. +using MS.Internal.YourAssemblyName; +#endif + +namespace MS.Utility +{ + // These classes implement a frugal storage model for key/value pair data + // structures. The keys are integers, and the values objects. + // Performance measurements show that Avalon has many maps that contain a + // single key/value pair. Therefore these classes are structured to prefer + // a map that contains a single key/value pair and uses a conservative + // growth strategy to minimize the steady state memory footprint. To enforce + // the slow growth the map does not allow the user to set the capacity. + // Also note that the map uses one fewer objects than the BCL HashTable and + // does no allocations at all until an item is inserted into the map. + // + // The code is also structured to perform well from a CPU standpoint. Perf + // analysis of DependencyObject showed that we used a single entry 63% of + // the time and growth tailed off quickly. Average access times are 8 to 16 + // times faster than a BCL Hashtable. + // + // FrugalMap is appropriate for small maps or maps that grow slowly. Its + // primary focus is for maps that contain fewer than 64 entries and that + // usually start with no entries, or a single entry. If you know your map + // will always have a minimum of 64 or more entires FrugalMap *may* not + // be the best choice. Choose your collections wisely and pay particular + // attention to the growth patterns and search methods. + + // This enum controls the growth to successively more complex storage models + internal enum FrugalMapStoreState + { + Success, + ThreeObjectMap, + SixObjectMap, + Array, + SortedArray, + Hashtable + } + + abstract class FrugalMapBase + { + public abstract FrugalMapStoreState InsertEntry(int key, Object value); + + public abstract void RemoveEntry(int key); + + /// + /// Looks for an entry that contains the given key, null is returned if the + /// key is not found. + /// + public abstract Object Search(int key); + + + /// + /// A routine used by enumerators that need a sorted map + /// + public abstract void Sort(); + + /// + /// A routine used by enumerators to iterate through the map + /// + public abstract void GetKeyValuePair(int index, out int key, out Object value); + + /// + /// A routine used to iterate through all the entries in the map + /// + public abstract void Iterate(ArrayList list, FrugalMapIterationCallback callback); + + /// + /// Promotes the key/value pairs in the current collection to the next larger + /// and more complex storage model. + /// + public abstract void Promote(FrugalMapBase newMap); + + /// + /// Size of this data store + /// + public abstract int Count + { + get; + } + + protected const int INVALIDKEY = 0x7FFFFFFF; + + internal struct Entry + { + public int Key; + public Object Value; + } + } + + /// + /// A simple class to handle a single key/value pair + /// + internal sealed class SingleObjectMap : FrugalMapBase + { + public SingleObjectMap() + { + _loneEntry.Key = INVALIDKEY; + _loneEntry.Value = DependencyProperty.UnsetValue; + } + + public override FrugalMapStoreState InsertEntry(int key, Object value) + { + // If we don't have any entries or the existing entry is being overwritten, + // then we can use this map. Otherwise we have to promote. + if ((INVALIDKEY == _loneEntry.Key) || (key == _loneEntry.Key)) + { + Debug.Assert(INVALIDKEY != key); + + _loneEntry.Key = key; + _loneEntry.Value = value; + return FrugalMapStoreState.Success; + } + else + { + // Entry already used, move to an ThreeObjectMap + return FrugalMapStoreState.ThreeObjectMap; + } + } + + public override void RemoveEntry(int key) + { + // Wipe out the info in the only entry if it matches the key. + if (key == _loneEntry.Key) + { + _loneEntry.Key = INVALIDKEY; + _loneEntry.Value = DependencyProperty.UnsetValue; + } + } + + public override Object Search(int key) + { + if (key == _loneEntry.Key) + { + return _loneEntry.Value; + } + return DependencyProperty.UnsetValue; + } + + public override void Sort() + { + // Single items are already sorted. + } + + public override void GetKeyValuePair(int index, out int key, out Object value) + { + if (0 == index) + { + value = _loneEntry.Value; + key = _loneEntry.Key; + } + else + { + value = DependencyProperty.UnsetValue; + key = INVALIDKEY; + throw new ArgumentOutOfRangeException("index"); + } + } + + public override void Iterate(ArrayList list, FrugalMapIterationCallback callback) + { + if (Count == 1) + { + callback(list, _loneEntry.Key, _loneEntry.Value); + } + } + + public override void Promote(FrugalMapBase newMap) + { + if (FrugalMapStoreState.Success == newMap.InsertEntry(_loneEntry.Key, _loneEntry.Value)) + { + } + else + { + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + } + + // Size of this data store + public override int Count + { + get + { + if (INVALIDKEY != _loneEntry.Key) + { + return 1; + } + else + { + return 0; + } + } + } + + private Entry _loneEntry; + } + + + /// + /// A simple class to handle a single object with 3 key/value pairs. The pairs are stored unsorted + /// and uses a linear search. Perf analysis showed that this yielded better memory locality and + /// perf than an object and an array. + /// + /// + /// This map inserts at the last position. Any time we add to the map we set _sorted to false. If you need + /// to iterate through the map in sorted order you must call Sort before using GetKeyValuePair. + /// + internal sealed class ThreeObjectMap : FrugalMapBase + { + public override FrugalMapStoreState InsertEntry(int key, Object value) + { + // Check to see if we are updating an existing entry + Debug.Assert(INVALIDKEY != key); + + // First check if the key matches the key of one of the existing entries. + // If it does, overwrite the existing value and return success. + switch (_count) + { + case 1: + if (_entry0.Key == key) + { + _entry0.Value = value; + return FrugalMapStoreState.Success; + } + break; + + case 2: + if (_entry0.Key == key) + { + _entry0.Value = value; + return FrugalMapStoreState.Success; + } + if (_entry1.Key == key) + { + _entry1.Value = value; + return FrugalMapStoreState.Success; + } + break; + + case 3: + if (_entry0.Key == key) + { + _entry0.Value = value; + return FrugalMapStoreState.Success; + } + if (_entry1.Key == key) + { + _entry1.Value = value; + return FrugalMapStoreState.Success; + } + if (_entry2.Key == key) + { + _entry2.Value = value; + return FrugalMapStoreState.Success; + } + break; + + default: + break; + } + + // If we got past the above switch, that means this key + // doesn't exist in the map already so we should add it. + // Only add it if we're not at the size limit; otherwise + // we have to promote. + if (SIZE > _count) + { + // Space still available to store the value. Insert + // into the entry at _count (the next available slot). + switch (_count) + { + case 0: + _entry0.Key = key; + _entry0.Value = value; + _sorted = true; + break; + + case 1: + _entry1.Key = key; + _entry1.Value = value; + // We have added an entry to the array, so we may not be sorted any longer + _sorted = false; + break; + + case 2: + _entry2.Key = key; + _entry2.Value = value; + // We have added an entry to the array, so we may not be sorted any longer + _sorted = false; + break; + } + ++_count; + + return FrugalMapStoreState.Success; + } + else + { + // Array is full, move to a SixObjectMap + return FrugalMapStoreState.SixObjectMap; + } + } + + public override void RemoveEntry(int key) + { + // If the key matches an existing entry, wipe out the last + // entry and move all the other entries up. Because we only + // have three entries we can just unravel all the cases. + switch (_count) + { + case 1: + if (_entry0.Key == key) + { + _entry0.Key = INVALIDKEY; + _entry0.Value = DependencyProperty.UnsetValue; + --_count; + return; + } + break; + + case 2: + if (_entry0.Key == key) + { + _entry0 = _entry1; + _entry1.Key = INVALIDKEY; + _entry1.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry1.Key == key) + { + _entry1.Key = INVALIDKEY; + _entry1.Value = DependencyProperty.UnsetValue; + --_count; + } + break; + + case 3: + if (_entry0.Key == key) + { + _entry0 = _entry1; + _entry1 = _entry2; + _entry2.Key = INVALIDKEY; + _entry2.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry1.Key == key) + { + _entry1 = _entry2; + _entry2.Key = INVALIDKEY; + _entry2.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry2.Key == key) + { + _entry2.Key = INVALIDKEY; + _entry2.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + break; + + default: + break; + } + } + + public override Object Search(int key) + { + Debug.Assert(INVALIDKEY != key); + if (_count > 0) + { + if (_entry0.Key == key) + { + return _entry0.Value; + } + if (_count > 1) + { + if (_entry1.Key == key) + { + return _entry1.Value; + } + if ((_count > 2) && (_entry2.Key == key)) + { + return _entry2.Value; + } + } + } + return DependencyProperty.UnsetValue; + } + + public override void Sort() + { + // If we're unsorted and we have entries to sort, do a simple + // sort. Sort the pairs (0,1), (1,2) and then (0,1) again. + if ((false == _sorted) && (_count > 1)) + { + Entry temp; + if (_entry0.Key > _entry1.Key) + { + temp = _entry0; + _entry0 = _entry1; + _entry1 = temp; + } + if (_count > 2) + { + if (_entry1.Key > _entry2.Key) + { + temp = _entry1; + _entry1 = _entry2; + _entry2 = temp; + + if (_entry0.Key > _entry1.Key) + { + temp = _entry0; + _entry0 = _entry1; + _entry1 = temp; + } + } + } + _sorted = true; + } + } + + public override void GetKeyValuePair(int index, out int key, out Object value) + { + if (index < _count) + { + switch (index) + { + case 0: + key = _entry0.Key; + value = _entry0.Value; + break; + + case 1: + key = _entry1.Key; + value = _entry1.Value; + break; + + case 2: + key = _entry2.Key; + value = _entry2.Value; + break; + + default: + key = INVALIDKEY; + value = DependencyProperty.UnsetValue; + break; + } + } + else + { + key = INVALIDKEY; + value = DependencyProperty.UnsetValue; + throw new ArgumentOutOfRangeException("index"); + } + } + + public override void Iterate(ArrayList list, FrugalMapIterationCallback callback) + { + if (_count > 0) + { + if (_count >= 1) + { + callback(list, _entry0.Key, _entry0.Value); + } + if (_count >= 2) + { + callback(list, _entry1.Key, _entry1.Value); + } + if (_count == 3) + { + callback(list, _entry2.Key, _entry2.Value); + } + } + } + + public override void Promote(FrugalMapBase newMap) + { + if (FrugalMapStoreState.Success != newMap.InsertEntry(_entry0.Key, _entry0.Value)) + { + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + if (FrugalMapStoreState.Success != newMap.InsertEntry(_entry1.Key, _entry1.Value)) + { + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + if (FrugalMapStoreState.Success != newMap.InsertEntry(_entry2.Key, _entry2.Value)) + { + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + } + + // Size of this data store + public override int Count + { + get + { + return _count; + } + } + + private const int SIZE = 3; + + // The number of items in the map. + private UInt16 _count; + + private bool _sorted; + private Entry _entry0; + private Entry _entry1; + private Entry _entry2; + } + + /// + /// A simple class to handle a single object with 6 key/value pairs. The pairs are stored unsorted + /// and uses a linear search. Perf analysis showed that this yielded better memory locality and + /// perf than an object and an array. + /// + /// + /// This map inserts at the last position. Any time we add to the map we set _sorted to false. If you need + /// to iterate through the map in sorted order you must call Sort before using GetKeyValuePair. + /// + internal sealed class SixObjectMap : FrugalMapBase + { + public override FrugalMapStoreState InsertEntry(int key, Object value) + { + // Check to see if we are updating an existing entry + Debug.Assert(INVALIDKEY != key); + + // First check if the key matches the key of one of the existing entries. + // If it does, overwrite the existing value and return success. + if (_count > 0) + { + if (_entry0.Key == key) + { + _entry0.Value = value; + return FrugalMapStoreState.Success; + } + if (_count > 1) + { + if (_entry1.Key == key) + { + _entry1.Value = value; + return FrugalMapStoreState.Success; + } + if (_count > 2) + { + if (_entry2.Key == key) + { + _entry2.Value = value; + return FrugalMapStoreState.Success; + } + if (_count > 3) + { + if (_entry3.Key == key) + { + _entry3.Value = value; + return FrugalMapStoreState.Success; + } + if (_count > 4) + { + if (_entry4.Key == key) + { + _entry4.Value = value; + return FrugalMapStoreState.Success; + } + if ((_count > 5) && (_entry5.Key == key)) + { + _entry5.Value = value; + return FrugalMapStoreState.Success; + } + } + } + } + } + } + + // If we got past the above switch, that means this key + // doesn't exist in the map already so we should add it. + // Only add it if we're not at the size limit; otherwise + // we have to promote. + if (SIZE > _count) + { + // We are adding an entry to the array, so we may not be sorted any longer + _sorted = false; + + // Space still available to store the value. Insert + // into the entry at _count (the next available slot). + switch (_count) + { + case 0: + _entry0.Key = key; + _entry0.Value = value; + + // Single entries are always sorted + _sorted = true; + break; + + case 1: + _entry1.Key = key; + _entry1.Value = value; + break; + + case 2: + _entry2.Key = key; + _entry2.Value = value; + break; + + case 3: + _entry3.Key = key; + _entry3.Value = value; + break; + + case 4: + _entry4.Key = key; + _entry4.Value = value; + break; + + case 5: + _entry5.Key = key; + _entry5.Value = value; + break; + } + ++_count; + + return FrugalMapStoreState.Success; + } + else + { + // Array is full, move to a Array + return FrugalMapStoreState.Array; + } + } + + public override void RemoveEntry(int key) + { + // If the key matches an existing entry, wipe out the last + // entry and move all the other entries up. Because we only + // have three entries we can just unravel all the cases. + switch (_count) + { + case 1: + if (_entry0.Key == key) + { + _entry0.Key = INVALIDKEY; + _entry0.Value = DependencyProperty.UnsetValue; + --_count; + return; + } + break; + + case 2: + if (_entry0.Key == key) + { + _entry0 = _entry1; + _entry1.Key = INVALIDKEY; + _entry1.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry1.Key == key) + { + _entry1.Key = INVALIDKEY; + _entry1.Value = DependencyProperty.UnsetValue; + --_count; + } + break; + + case 3: + if (_entry0.Key == key) + { + _entry0 = _entry1; + _entry1 = _entry2; + _entry2.Key = INVALIDKEY; + _entry2.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry1.Key == key) + { + _entry1 = _entry2; + _entry2.Key = INVALIDKEY; + _entry2.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry2.Key == key) + { + _entry2.Key = INVALIDKEY; + _entry2.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + break; + + case 4: + if (_entry0.Key == key) + { + _entry0 = _entry1; + _entry1 = _entry2; + _entry2 = _entry3; + _entry3.Key = INVALIDKEY; + _entry3.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry1.Key == key) + { + _entry1 = _entry2; + _entry2 = _entry3; + _entry3.Key = INVALIDKEY; + _entry3.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry2.Key == key) + { + _entry2 = _entry3; + _entry3.Key = INVALIDKEY; + _entry3.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry3.Key == key) + { + _entry3.Key = INVALIDKEY; + _entry3.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + break; + + case 5: + if (_entry0.Key == key) + { + _entry0 = _entry1; + _entry1 = _entry2; + _entry2 = _entry3; + _entry3 = _entry4; + _entry4.Key = INVALIDKEY; + _entry4.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry1.Key == key) + { + _entry1 = _entry2; + _entry2 = _entry3; + _entry3 = _entry4; + _entry4.Key = INVALIDKEY; + _entry4.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry2.Key == key) + { + _entry2 = _entry3; + _entry3 = _entry4; + _entry4.Key = INVALIDKEY; + _entry4.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry3.Key == key) + { + _entry3 = _entry4; + _entry4.Key = INVALIDKEY; + _entry4.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry4.Key == key) + { + _entry4.Key = INVALIDKEY; + _entry4.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + break; + + case 6: + if (_entry0.Key == key) + { + _entry0 = _entry1; + _entry1 = _entry2; + _entry2 = _entry3; + _entry3 = _entry4; + _entry4 = _entry5; + _entry5.Key = INVALIDKEY; + _entry5.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry1.Key == key) + { + _entry1 = _entry2; + _entry2 = _entry3; + _entry3 = _entry4; + _entry4 = _entry5; + _entry5.Key = INVALIDKEY; + _entry5.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry2.Key == key) + { + _entry2 = _entry3; + _entry3 = _entry4; + _entry4 = _entry5; + _entry5.Key = INVALIDKEY; + _entry5.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry3.Key == key) + { + _entry3 = _entry4; + _entry4 = _entry5; + _entry5.Key = INVALIDKEY; + _entry5.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry4.Key == key) + { + _entry4 = _entry5; + _entry5.Key = INVALIDKEY; + _entry5.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + if (_entry5.Key == key) + { + _entry5.Key = INVALIDKEY; + _entry5.Value = DependencyProperty.UnsetValue; + --_count; + break; + } + break; + + default: + break; + } + } + + public override Object Search(int key) + { + Debug.Assert(INVALIDKEY != key); + if (_count > 0) + { + if (_entry0.Key == key) + { + return _entry0.Value; + } + if (_count > 1) + { + if (_entry1.Key == key) + { + return _entry1.Value; + } + if (_count > 2) + { + if (_entry2.Key == key) + { + return _entry2.Value; + } + if (_count > 3) + { + if (_entry3.Key == key) + { + return _entry3.Value; + } + if (_count > 4) + { + if (_entry4.Key == key) + { + return _entry4.Value; + } + if ((_count > 5) && (_entry5.Key == key)) + { + return _entry5.Value; + } + } + } + } + } + } + return DependencyProperty.UnsetValue; + } + + public override void Sort() + { + // If we're unsorted and we have entries to sort, do a simple + // bubble sort. Sort the pairs, 0..5, and then again until we no + // longer do any swapping. + if ((false == _sorted) && (_count > 1)) + { + bool swapped; + + do + { + swapped = false; + + Entry temp; + if (_entry0.Key > _entry1.Key) + { + temp = _entry0; + _entry0 = _entry1; + _entry1 = temp; + swapped = true; + } + if (_count > 2) + { + if (_entry1.Key > _entry2.Key) + { + temp = _entry1; + _entry1 = _entry2; + _entry2 = temp; + swapped = true; + } + if (_count > 3) + { + if (_entry2.Key > _entry3.Key) + { + temp = _entry2; + _entry2 = _entry3; + _entry3 = temp; + swapped = true; + } + if (_count > 4) + { + if (_entry3.Key > _entry4.Key) + { + temp = _entry3; + _entry3 = _entry4; + _entry4 = temp; + swapped = true; + } + if (_count > 5) + { + if (_entry4.Key > _entry5.Key) + { + temp = _entry4; + _entry4 = _entry5; + _entry5 = temp; + swapped = true; + } + } + } + } + } + } + while (swapped); + _sorted = true; + } + } + + public override void GetKeyValuePair(int index, out int key, out Object value) + { + if (index < _count) + { + switch (index) + { + case 0: + key = _entry0.Key; + value = _entry0.Value; + break; + + case 1: + key = _entry1.Key; + value = _entry1.Value; + break; + + case 2: + key = _entry2.Key; + value = _entry2.Value; + break; + + case 3: + key = _entry3.Key; + value = _entry3.Value; + break; + + case 4: + key = _entry4.Key; + value = _entry4.Value; + break; + + case 5: + key = _entry5.Key; + value = _entry5.Value; + break; + + default: + key = INVALIDKEY; + value = DependencyProperty.UnsetValue; + break; + } + } + else + { + key = INVALIDKEY; + value = DependencyProperty.UnsetValue; + throw new ArgumentOutOfRangeException("index"); + } + } + + public override void Iterate(ArrayList list, FrugalMapIterationCallback callback) + { + if (_count > 0) + { + if (_count >= 1) + { + callback(list, _entry0.Key, _entry0.Value); + } + if (_count >= 2) + { + callback(list, _entry1.Key, _entry1.Value); + } + if (_count >= 3) + { + callback(list, _entry2.Key, _entry2.Value); + } + if (_count >= 4) + { + callback(list, _entry3.Key, _entry3.Value); + } + if (_count >= 5) + { + callback(list, _entry4.Key, _entry4.Value); + } + if (_count == 6) + { + callback(list, _entry5.Key, _entry5.Value); + } + } + } + + public override void Promote(FrugalMapBase newMap) + { + if (FrugalMapStoreState.Success != newMap.InsertEntry(_entry0.Key, _entry0.Value)) + { + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + if (FrugalMapStoreState.Success != newMap.InsertEntry(_entry1.Key, _entry1.Value)) + { + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + if (FrugalMapStoreState.Success != newMap.InsertEntry(_entry2.Key, _entry2.Value)) + { + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + if (FrugalMapStoreState.Success != newMap.InsertEntry(_entry3.Key, _entry3.Value)) + { + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + if (FrugalMapStoreState.Success != newMap.InsertEntry(_entry4.Key, _entry4.Value)) + { + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + if (FrugalMapStoreState.Success != newMap.InsertEntry(_entry5.Key, _entry5.Value)) + { + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + } + + // Size of this data store + public override int Count + { + get + { + return _count; + } + } + + private const int SIZE = 6; + + // The number of items in the map. + private UInt16 _count; + + private bool _sorted; + private Entry _entry0; + private Entry _entry1; + private Entry _entry2; + private Entry _entry3; + private Entry _entry4; + private Entry _entry5; + } + + /// + /// A simple class to handle an array of between 6 and 12 key/value pairs. It is unsorted + /// and uses a linear search. Perf analysis showed that this was the optimal size for both + /// memory and perf. The values may need to be adjusted as the CLR and Avalon evolve. + /// + internal sealed class ArrayObjectMap : FrugalMapBase + { + public override FrugalMapStoreState InsertEntry(int key, Object value) + { + // Check to see if we are updating an existing entry + for (int index = 0; index < _count; ++index) + { + Debug.Assert(INVALIDKEY != key); + + if (_entries[index].Key == key) + { + _entries[index].Value = value; + return FrugalMapStoreState.Success; + } + } + + // New key/value pair + if (MAXSIZE > _count) + { + // Space still available to store the value + if (null != _entries) + { + // We are adding an entry to the array, so we may not be sorted any longer + _sorted = false; + + if (_entries.Length > _count) + { + // Have empty entries, just set the first available + } + else + { + Entry[] destEntries = new Entry[_entries.Length + GROWTH]; + + // Copy old array + Array.Copy(_entries, 0, destEntries, 0, _entries.Length); + _entries = destEntries; + } + } + else + { + _entries = new Entry[MINSIZE]; + + // No entries, must be sorted + _sorted = true; + } + + // Stuff in the new key/value pair + _entries[_count].Key = key; + _entries[_count].Value = value; + + // Bump the count for the entry just added. + ++_count; + + return FrugalMapStoreState.Success; + } + else + { + // Array is full, move to a SortedArray + return FrugalMapStoreState.SortedArray; + } + } + + public override void RemoveEntry(int key) + { + for (int index = 0; index < _count; ++index) + { + if (_entries[index].Key == key) + { + // Shift entries down + int numToCopy = (_count - index) - 1; + if (numToCopy > 0) + { + Array.Copy(_entries, index + 1, _entries, index, numToCopy); + } + + // Wipe out the last entry + _entries[_count - 1].Key = INVALIDKEY; + _entries[_count - 1].Value = DependencyProperty.UnsetValue; + --_count; + break; + } + } + } + + public override Object Search(int key) + { + for (int index = 0; index < _count; ++index) + { + if (key == _entries[index].Key) + { + return _entries[index].Value; + } + } + return DependencyProperty.UnsetValue; + } + + public override void Sort() + { + if ((false == _sorted) && (_count > 1)) + { + QSort(0, (_count - 1)); + _sorted = true; + } + } + + public override void GetKeyValuePair(int index, out int key, out Object value) + { + if (index < _count) + { + value = _entries[index].Value; + key = _entries[index].Key; + } + else + { + value = DependencyProperty.UnsetValue; + key = INVALIDKEY; + throw new ArgumentOutOfRangeException("index"); + } + } + + public override void Iterate(ArrayList list, FrugalMapIterationCallback callback) + { + if (_count > 0) + { + for (int i=0; i< _count; i++) + { + callback(list, _entries[i].Key, _entries[i].Value); + } + } + } + + public override void Promote(FrugalMapBase newMap) + { + for (int index = 0; index < _entries.Length; ++index) + { + if (FrugalMapStoreState.Success == newMap.InsertEntry(_entries[index].Key, _entries[index].Value)) + { + continue; + } + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + } + + // Size of this data store + public override int Count + { + get + { + return _count; + } + } + + // Compare two Entry nodes in the _entries array + private int Compare(int left, int right) + { + return (_entries[left].Key - _entries[right].Key); + } + + // Partition the _entries array for QuickSort + private int Partition(int left, int right) + { + int pivot = right; + int i = left - 1; + int j = right; + Entry temp; + + for (;;) + { + while (Compare(++i, pivot) < 0); + while (Compare(pivot, --j) < 0) + { + if (j == left) + { + break; + } + } + if (i >= j) + { + break; + } + temp = _entries[j]; + _entries[j] = _entries[i]; + _entries[i] = temp; + } + temp = _entries[right]; + _entries[right] = _entries[i]; + _entries[i] = temp; + return i; + } + + // Sort the _entries array using an index based QuickSort + private void QSort(int left, int right) + { + if (left < right) + { + int pivot = Partition(left, right); + QSort(left, pivot - 1); + QSort(pivot + 1, right); + } + } + + // MINSIZE and GROWTH chosen to minimize memory footprint + private const int MINSIZE = 9; + private const int MAXSIZE = 15; + private const int GROWTH = 3; + + // The number of items in the map. + private UInt16 _count; + + private bool _sorted; + private Entry[] _entries; + } + + // A sorted array of key/value pairs. A binary search is used to minimize the cost of insert/search. + + internal sealed class SortedObjectMap : FrugalMapBase + { + public override FrugalMapStoreState InsertEntry(int key, Object value) + { + bool found; + + Debug.Assert(INVALIDKEY != key); + + // Check to see if we are updating an existing entry + int index = FindInsertIndex(key, out found); + if (found) + { + _entries[index].Value = value; + return FrugalMapStoreState.Success; + } + else + { + // New key/value pair + if (MAXSIZE > _count) + { + // Less than the maximum array size + if (null != _entries) + { + if (_entries.Length > _count) + { + // Have empty entries, just set the first available + } + else + { + Entry[] destEntries = new Entry[_entries.Length + GROWTH]; + + // Copy old array + Array.Copy(_entries, 0, destEntries, 0, _entries.Length); + _entries = destEntries; + } + } + else + { + _entries = new Entry[MINSIZE]; + } + + // Inserting into the middle of the existing entries? + if (index < _count) + { + // Move higher valued keys to make room for the new key + Array.Copy(_entries, index, _entries, index + 1, (_count - index)); + } + else + { + _lastKey = key; + } + + // Stuff in the new key/value pair + _entries[index].Key = key; + _entries[index].Value = value; + ++_count; + return FrugalMapStoreState.Success; + } + else + { + // SortedArray is full, move to a hashtable + return FrugalMapStoreState.Hashtable; + } + } + } + + public override void RemoveEntry(int key) + { + bool found; + + Debug.Assert(INVALIDKEY != key); + + int index = FindInsertIndex(key, out found); + + if (found) + { + // Shift entries down + int numToCopy = (_count - index) - 1; + if (numToCopy > 0) + { + Array.Copy(_entries, index + 1, _entries, index, numToCopy); + } + else + { + // If we're not copying anything, then it means we are + // going to remove the last entry. Update _lastKey so + // that it reflects the key of the new "last entry" + if( _count > 1 ) + { + // Next-to-last entry will be the new last entry + _lastKey = _entries[_count - 2].Key; + } + else + { + // Unless there isn't a next-to-last entry, in which + // case the key is reset to INVALIDKEY. + _lastKey = INVALIDKEY; + } + } + + // Wipe out the last entry + _entries[_count - 1].Key = INVALIDKEY; + _entries[_count - 1].Value = DependencyProperty.UnsetValue; + + --_count; + } + } + + public override Object Search(int key) + { + bool found; + + int index = FindInsertIndex(key, out found); + if (found) + { + return _entries[index].Value; + } + return DependencyProperty.UnsetValue; + } + + public override void Sort() + { + // Always sorted. + } + + public override void GetKeyValuePair(int index, out int key, out Object value) + { + if (index < _count) + { + value = _entries[index].Value; + key = _entries[index].Key; + } + else + { + value = DependencyProperty.UnsetValue; + key = INVALIDKEY; + throw new ArgumentOutOfRangeException("index"); + } + } + + public override void Iterate(ArrayList list, FrugalMapIterationCallback callback) + { + if (_count > 0) + { + for (int i=0; i< _count; i++) + { + callback(list, _entries[i].Key, _entries[i].Value); + } + } + } + + public override void Promote(FrugalMapBase newMap) + { + for (int index = 0; index < _entries.Length; ++index) + { + if (FrugalMapStoreState.Success == newMap.InsertEntry(_entries[index].Key, _entries[index].Value)) + { + continue; + } + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + } + + private int FindInsertIndex(int key, out bool found) + { + int iLo = 0; + + // Only do the binary search if there is a chance of finding the key + // This also speeds insertion because we tend to insert at the end. + if ((_count > 0) && (key <= _lastKey)) + { + // The array index used for insertion is somewhere between 0 + // and _count-1 inclusive + int iHi = _count-1; + + // Do a binary search to find the insertion point + do + { + int iPv = (iHi + iLo) / 2; + if (key <= _entries[iPv].Key) + { + iHi = iPv; + } + else + { + iLo = iPv + 1; + } + } + while (iLo < iHi); + found = (key == _entries[iLo].Key); + } + else + { + // Insert point is at the end + iLo = _count; + found = false; + } + return iLo; + } + + public override int Count + { + get + { + return _count; + } + } + + // MINSIZE chosen to be larger than MAXSIZE of the ArrayObjectMap with some extra space for new values + // The MAXSIZE and GROWTH are chosen to minimize memory usage as we grow the array + private const int MINSIZE = 16; + private const int MAXSIZE = 128; + private const int GROWTH = 8; + + // The number of items in the map. + internal int _count; + + private int _lastKey = INVALIDKEY; + private Entry[] _entries; + } + + internal sealed class HashObjectMap : FrugalMapBase + { + public override FrugalMapStoreState InsertEntry(int key, Object value) + { + Debug.Assert(INVALIDKEY != key); + + if (null != _entries) + { + // This is done because forward branches + // default prediction is not to be taken + // making this a CPU win because insert + // is a common operation. + } + else + { + _entries = new Hashtable(MINSIZE); + } + + _entries[key] = ((value != NullValue) && (value != null)) ? value : NullValue; + return FrugalMapStoreState.Success; + } + + public override void RemoveEntry(int key) + { + _entries.Remove(key); + } + + public override Object Search(int key) + { + object value = _entries[key]; + + return ((value != NullValue) && (value != null)) ? value : DependencyProperty.UnsetValue; + } + + public override void Sort() + { + // Always sorted. + } + + public override void GetKeyValuePair(int index, out int key, out Object value) + { + if (index < _entries.Count) + { + IDictionaryEnumerator myEnumerator = _entries.GetEnumerator(); + + // Move to first valid value + myEnumerator.MoveNext(); + + for (int i = 0; i < index; ++i) + { + myEnumerator.MoveNext(); + } + key = (int)myEnumerator.Key; + if ((myEnumerator.Value != NullValue) && (myEnumerator.Value != null)) + { + value = myEnumerator.Value; + } + else + { + value = DependencyProperty.UnsetValue; + } + } + else + { + value = DependencyProperty.UnsetValue; + key = INVALIDKEY; + throw new ArgumentOutOfRangeException("index"); + } + } + + public override void Iterate(ArrayList list, FrugalMapIterationCallback callback) + { + IDictionaryEnumerator myEnumerator = _entries.GetEnumerator(); + + while (myEnumerator.MoveNext()) + { + int key = (int)myEnumerator.Key; + object value; + if ((myEnumerator.Value != NullValue) && (myEnumerator.Value != null)) + { + value = myEnumerator.Value; + } + else + { + value = DependencyProperty.UnsetValue; + } + + callback(list, key, value); + } + } + + public override void Promote(FrugalMapBase newMap) + { + // Should never get here + throw new InvalidOperationException(SR.Get(SRID.FrugalMap_CannotPromoteBeyondHashtable)); + } + + // Size of this data store + public override int Count + { + get + { + return _entries.Count; + } + } + + // 163 is chosen because it is the first prime larger than 128, the MAXSIZE of SortedObjectMap + internal const int MINSIZE = 163; + + // Hashtable will return null from its indexer if the key is not + // found OR if the value is null. To distinguish between these + // two cases we insert NullValue instead of null. + private static object NullValue = new object(); + + internal Hashtable _entries; + } + + [FriendAccessAllowed] + internal struct FrugalMap + { + public object this[int key] + { + get + { + // If no entry, DependencyProperty.UnsetValue is returned + if (null != _mapStore) + { + return _mapStore.Search(key); + } + return DependencyProperty.UnsetValue; + } + + set + { + if (value != DependencyProperty.UnsetValue) + { + // If not unset value, ensure write success + if (null != _mapStore) + { + // This is done because forward branches + // default prediction is not to be taken + // making this a CPU win because set is + // a common operation. + } + else + { + _mapStore = new SingleObjectMap(); + } + + FrugalMapStoreState myState = _mapStore.InsertEntry(key, value); + if (FrugalMapStoreState.Success == myState) + { + return; + } + else + { + // Need to move to a more complex storage + FrugalMapBase newStore; + + if (FrugalMapStoreState.ThreeObjectMap == myState) + { + newStore = new ThreeObjectMap(); + } + else if (FrugalMapStoreState.SixObjectMap == myState) + { + newStore = new SixObjectMap(); + } + else if (FrugalMapStoreState.Array == myState) + { + newStore = new ArrayObjectMap(); + } + else if (FrugalMapStoreState.SortedArray == myState) + { + newStore = new SortedObjectMap(); + } + else if (FrugalMapStoreState.Hashtable == myState) + { + newStore = new HashObjectMap(); + } + else + { + throw new InvalidOperationException(SR.Get(SRID.FrugalMap_CannotPromoteBeyondHashtable)); + } + + // Extract the values from the old store and insert them into the new store + _mapStore.Promote(newStore); + + // Insert the new value + _mapStore = newStore; + _mapStore.InsertEntry(key, value); + } + } + else + { + // DependencyProperty.UnsetValue means remove the value + if (null != _mapStore) + { + _mapStore.RemoveEntry(key); + if (_mapStore.Count == 0) + { + // Map Store is now empty ... throw it away + _mapStore = null; + } + } + } + } + } + + public void Sort() + { + if (null != _mapStore) + { + _mapStore.Sort(); + } + } + + public void GetKeyValuePair(int index, out int key, out Object value) + { + if (null != _mapStore) + { + _mapStore.GetKeyValuePair(index, out key, out value); + } + else + { + throw new ArgumentOutOfRangeException("index"); + } + } + + public void Iterate(ArrayList list, FrugalMapIterationCallback callback) + { + if (null != callback) + { + if (null != list) + { + if (_mapStore != null) + { + _mapStore.Iterate(list, callback); + } + } + else + { + throw new ArgumentNullException("list"); + } + } + else + { + throw new ArgumentNullException("callback"); + } + } + + public int Count + { + get + { + if (null != _mapStore) + { + return _mapStore.Count; + } + return 0; + } + } + + internal FrugalMapBase _mapStore; + } + + // A sorted array of key/value pairs. A binary search is used to minimize the cost of insert/search. + + internal sealed class LargeSortedObjectMap : FrugalMapBase + { + public override FrugalMapStoreState InsertEntry(int key, Object value) + { + bool found; + + Debug.Assert(INVALIDKEY != key); + + // Check to see if we are updating an existing entry + int index = FindInsertIndex(key, out found); + if (found) + { + _entries[index].Value = value; + return FrugalMapStoreState.Success; + } + else + { + // New key/value pair + if (null != _entries) + { + if (_entries.Length > _count) + { + // Have empty entries, just set the first available + } + else + { + int size = _entries.Length; + Entry[] destEntries = new Entry[size + (size >> 1)]; + + // Copy old array + Array.Copy(_entries, 0, destEntries, 0, _entries.Length); + _entries = destEntries; + } + } + else + { + _entries = new Entry[MINSIZE]; + } + + // Inserting into the middle of the existing entries? + if (index < _count) + { + // Move higher valued keys to make room for the new key + Array.Copy(_entries, index, _entries, index + 1, (_count - index)); + } + else + { + _lastKey = key; + } + + // Stuff in the new key/value pair + _entries[index].Key = key; + _entries[index].Value = value; + ++_count; + return FrugalMapStoreState.Success; + } + } + + public override void RemoveEntry(int key) + { + bool found; + + Debug.Assert(INVALIDKEY != key); + + int index = FindInsertIndex(key, out found); + + if (found) + { + // Shift entries down + int numToCopy = (_count - index) - 1; + if (numToCopy > 0) + { + Array.Copy(_entries, index + 1, _entries, index, numToCopy); + } + else + { + // If we're not copying anything, then it means we are + // going to remove the last entry. Update _lastKey so + // that it reflects the key of the new "last entry" + if( _count > 1 ) + { + // Next-to-last entry will be the new last entry + _lastKey = _entries[_count - 2].Key; + } + else + { + // Unless there isn't a next-to-last entry, in which + // case the key is reset to INVALIDKEY. + _lastKey = INVALIDKEY; + } + } + + // Wipe out the last entry + _entries[_count - 1].Key = INVALIDKEY; + _entries[_count - 1].Value = DependencyProperty.UnsetValue; + + --_count; + } + } + + public override Object Search(int key) + { + bool found; + + int index = FindInsertIndex(key, out found); + if (found) + { + return _entries[index].Value; + } + return DependencyProperty.UnsetValue; + } + + public override void Sort() + { + // Always sorted. + } + + public override void GetKeyValuePair(int index, out int key, out Object value) + { + if (index < _count) + { + value = _entries[index].Value; + key = _entries[index].Key; + } + else + { + value = DependencyProperty.UnsetValue; + key = INVALIDKEY; + throw new ArgumentOutOfRangeException("index"); + } + } + + public override void Iterate(ArrayList list, FrugalMapIterationCallback callback) + { + if (_count > 0) + { + for (int i=0; i< _count; i++) + { + callback(list, _entries[i].Key, _entries[i].Value); + } + } + } + + public override void Promote(FrugalMapBase newMap) + { + for (int index = 0; index < _entries.Length; ++index) + { + if (FrugalMapStoreState.Success == newMap.InsertEntry(_entries[index].Key, _entries[index].Value)) + { + continue; + } + // newMap is smaller than previous map + throw new ArgumentException(SR.Get(SRID.FrugalMap_TargetMapCannotHoldAllData, this.ToString(), newMap.ToString()), "newMap"); + } + } + + private int FindInsertIndex(int key, out bool found) + { + int iLo = 0; + + // Only do the binary search if there is a chance of finding the key + // This also speeds insertion because we tend to insert at the end. + if ((_count > 0) && (key <= _lastKey)) + { + // The array index used for insertion is somewhere between 0 + // and _count-1 inclusive + int iHi = _count-1; + + // Do a binary search to find the insertion point + do + { + int iPv = (iHi + iLo) / 2; + if (key <= _entries[iPv].Key) + { + iHi = iPv; + } + else + { + iLo = iPv + 1; + } + } + while (iLo < iHi); + found = (key == _entries[iLo].Key); + } + else + { + // Insert point is at the end + iLo = _count; + found = false; + } + return iLo; + } + + public override int Count + { + get + { + return _count; + } + } + + // MINSIZE chosen to be small, growth rate of 1.5 is slow at small sizes, but increasingly agressive as + // the array grows + private const int MINSIZE = 2; + + // The number of items in the map. + internal int _count; + + private int _lastKey = INVALIDKEY; + private Entry[] _entries; + } + + // This is a variant of FrugalMap that always uses an array as the underlying store. + // This avoids the virtual method calls that are present when the store morphs through + // the size efficient store classes normally used. It is appropriate only when we know the + // store will always be populated and individual elements will be accessed in a tight loop. + internal struct InsertionSortMap + { + public object this[int key] + { + get + { + // If no entry, DependencyProperty.UnsetValue is returned + if (null != _mapStore) + { + return _mapStore.Search(key); + } + return DependencyProperty.UnsetValue; + } + + set + { + if (value != DependencyProperty.UnsetValue) + { + // If not unset value, ensure write success + if (null != _mapStore) + { + // This is done because forward branches + // default prediction is not to be taken + // making this a CPU win because set is + // a common operation. + } + else + { + _mapStore = new LargeSortedObjectMap(); + } + + FrugalMapStoreState myState = _mapStore.InsertEntry(key, value); + if (FrugalMapStoreState.Success == myState) + { + return; + } + else + { + // Need to move to a more complex storage + LargeSortedObjectMap newStore; + + if (FrugalMapStoreState.SortedArray == myState) + { + newStore = new LargeSortedObjectMap(); + } + else + { + throw new InvalidOperationException(SR.Get(SRID.FrugalMap_CannotPromoteBeyondHashtable)); + } + + // Extract the values from the old store and insert them into the new store + _mapStore.Promote(newStore); + + // Insert the new value + _mapStore = newStore; + _mapStore.InsertEntry(key, value); + } + } + else + { + // DependencyProperty.UnsetValue means remove the value + if (null != _mapStore) + { + _mapStore.RemoveEntry(key); + if (_mapStore.Count == 0) + { + // Map Store is now empty ... throw it away + _mapStore = null; + } + } + } + } + } + + public void Sort() + { + if (null != _mapStore) + { + _mapStore.Sort(); + } + } + + public void GetKeyValuePair(int index, out int key, out Object value) + { + if (null != _mapStore) + { + _mapStore.GetKeyValuePair(index, out key, out value); + } + else + { + throw new ArgumentOutOfRangeException("index"); + } + } + + public void Iterate(ArrayList list, FrugalMapIterationCallback callback) + { + if (null != callback) + { + if (null != list) + { + if (_mapStore != null) + { + _mapStore.Iterate(list, callback); + } + } + else + { + throw new ArgumentNullException("list"); + } + } + else + { + throw new ArgumentNullException("callback"); + } + } + + public int Count + { + get + { + if (null != _mapStore) + { + return _mapStore.Count; + } + return 0; + } + } + + internal LargeSortedObjectMap _mapStore; + } + + /// + /// FrugalMapIterationCallback + /// + internal delegate void FrugalMapIterationCallback(ArrayList list, int key, object value); +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/ItemList.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/ItemList.cs new file mode 100644 index 00000000000..848eb37358b --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/ItemList.cs @@ -0,0 +1,194 @@ +using System; +using MS.Internal.WindowsBase; + +namespace MS.Utility +{ + // + // ItemStructList + // + + [FriendAccessAllowed] // Built into Base, also used by Framework. + internal struct ItemStructList + { + public ItemStructList(int capacity) + { + List = new T[capacity]; + Count = 0; + } + + + // + // Non-lock-required Read methods + // (Always safe to call when locking "safe" write operations are used) + // + + public T[] List; + public int Count; + + public void EnsureIndex(int index) + { + int delta = (index + 1) - Count; + if (delta > 0) + { + Add(delta); + } + } + + public bool IsValidIndex(int index) + { + return (index >= 0 && index < Count); + } + + public int IndexOf(T value) + { + int index = -1; + + for (int i = 0; i < Count; i++) + { + if (List[i].Equals(value)) + { + index = i; + break; + } + } + + return index; + } + + public bool Contains(T value) + { + return (IndexOf(value) != -1); + } + + + // + // Lock-required Write operations + // "Safe" methods for Reader lock-free operation + // + + // Increase size by one, new value is provided + public void Add(T item) + { + // Add without Count adjustment (incr Count after valid item added) + int index = Add(1, false); + List[index] = item; + Count++; + } + + // Increase size by one, new value is provided + public void Add(ref T item) + { + // Add without Count adjustment (incr Count after valid item added) + int index = Add(1, false); + List[index] = item; + Count++; + } + + // Increase size by one, new value is default value + public int Add() + { + return Add(1, true); + } + + // Increase size of array by delta, fill with default values + public int Add(int delta) + { + return Add(delta, true); + } + + // Increase size of array by delta, fill with default values + // Allow disable of automatic Count increment so that cases where + // non-default values are to be added to the list can be done before + // count is changed. This is important for non-locking scenarios + // (i.e. count is adjusted after array size changes) + private int Add(int delta, bool incrCount) + { + if (List != null) + { + if ((Count + delta) > List.Length) + { + T[] newList = new T[Math.Max(List.Length * 2, Count + delta)]; + List.CopyTo(newList, 0); + List = newList; + } + } + else + { + List = new T[Math.Max(delta, 2)]; + } + + // New arrays auto-initialized to default entry values + // Any resued entried have already been cleared out by Remove or Clear + + int index = Count; + + // Optional adjustment of Count + if (incrCount) + { + // Adjust count after resize so that array bounds and data + // are never invalid (good for locking writes without synchronized reads) + Count += delta; + } + + return index; + } + + public void Sort() + { + if (List != null) + { + Array.Sort(List, 0, Count); + } + } + + public void AppendTo(ref ItemStructList destinationList) + { + for (int i = 0; i < Count; i++) + { + destinationList.Add(ref List[i]); + } + } + + public T[] ToArray() + { + T[] array = new T[Count]; + Array.Copy(List, 0, array, 0, Count); + + return array; + } + + + // + // Lock-required Write operations + // "UNSafe" methods for Reader lock-free operation + // + // If any of these methods are called, the entire class is considered + // unsafe for Reader lock-free operation for that point on (meaning + // Reader locks must be taken) + // + + public void Clear() + { + // Return now unused entries back to default + Array.Clear(List, 0, Count); + + Count = 0; + } + + public void Remove(T value) + { + int index = IndexOf(value); + if (index != -1) + { + // Shift entries down + Array.Copy(List, index + 1, List, index, (Count - index - 1)); + + // Return now unused entries back to default + Array.Clear(List, Count - 1, 1); + + Count--; + } + } + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/ItemMap.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/ItemMap.cs new file mode 100644 index 00000000000..03c266341b0 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/ItemMap.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections; +using System.Diagnostics; + +namespace MS.Utility +{ + // + // ItemStructMap + // + + // Disable warnings about fields never being assigned to + // This struct is designed to function with its fields starting at + // their default values and without the need of surfacing a constructor + // other than the deafult + #pragma warning disable 649 + + internal struct ItemStructMap + { + public int EnsureEntry(int key) + { + int index = Search(key); + if (index < 0) + { + // Not found, add Entry + + // Create initial capacity, if necessary + if (Entries == null) + { + Entries = new Entry[SearchTypeThreshold]; + } + + // Convert not-found index to insertion point + index = ~index; + + Entry[] destEntries = Entries; + + // Increase capacity, if necessary + if ((Count + 1) > Entries.Length) + { + destEntries = new Entry[Entries.Length * 2]; + + // Initialize start of new array + Array.Copy(Entries, 0, destEntries, 0, index); + } + + // Shift entries to make room for new key at provided insertion point + Array.Copy(Entries, index, destEntries, index + 1, Count - index); + + // Ensure Source and Destination arrays are the same + Entries = destEntries; + + // Clear new entry + Entries[index] = EmptyEntry; + + // Set + Entries[index].Key = key; + + Count++; + } + + return index; + } + + public int Search(int key) + { + int keyPv = Int32.MaxValue; + int iPv = 0; + + // Use fastest search based on size + if (Count > SearchTypeThreshold) + { + // Binary Search + int iLo = 0; + int iHi = Count - 1; + + while (iLo <= iHi) + { + iPv = (iHi + iLo) / 2; + keyPv = Entries[iPv].Key; + + if (key == keyPv) + { + return iPv; + } + + if (key < keyPv) + { + iHi = iPv - 1; + } + else + { + iLo = iPv + 1; + } + } + } + else + { + // Linear search + + for (int i = 0; i < Count; i++) + { + iPv = i; + keyPv = Entries[iPv].Key; + + if (key == keyPv) + { + return iPv; + } + + if (key < keyPv) + { + break; + } + } + } + + // iPv and keyPv will match and have the last pivot check + + // Return a negative value whose bitwise compliment + // is this index of the first Entry that is greater + // than the key passed in (sorted insertion point) + + if (key > keyPv) + { + iPv++; + } + + + return ~iPv; + } + + private const int SearchTypeThreshold = 4; + + public Entry[] Entries; + public int Count; + + public struct Entry + { + public int Key; + public T Value; + } + + private static Entry EmptyEntry; + } + + #pragma warning restore 649 +} + + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/Maps.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/Maps.cs new file mode 100644 index 00000000000..cb8b1e16584 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/Maps.cs @@ -0,0 +1,118 @@ +/***************************************************************************\ +* +* File: Maps.cs +* +* Description: +* Contains specialized data structures for mapping a key to data. +* +* Copyright (C) 2002 by Microsoft Corporation. All rights reserved. +* +\***************************************************************************/ + +using System; +using System.Collections; +using System.Windows; + +namespace MS.Utility +{ + /***************************************************************************\ + ***************************************************************************** + * + * DTypeMap (DType --> Object) + * + * Maps the first N used DependencyObject-derived types via an array + * (low constant time lookup) for mapping. After which falls back on a + * hash table. + * + * - Fastest gets and sets (normally single array access). + * - Large memory footprint. + * + * Starting mapping is all map to null + * + ***************************************************************************** + \***************************************************************************/ + + using MS.Internal.PresentationCore; + + [FriendAccessAllowed] // Built into Core, also used by Framework. + internal class DTypeMap + { + + public DTypeMap(int entryCount) + { + // Constant Time Lookup entries (array size) + _entryCount = entryCount; + _entries = new object[_entryCount]; + _activeDTypes = new ItemStructList(128); + } + + public object this[DependencyObjectType dType] + { + get + { + if (dType.Id < _entryCount) + { + return _entries[dType.Id]; + } + else + { + if (_overFlow != null) + { + return _overFlow[dType]; + } + + return null; + } + } + + set + { + if (dType.Id < _entryCount) + { + _entries[dType.Id] = value; + } + else + { + if (_overFlow == null) + { + _overFlow = new Hashtable(); + } + + _overFlow[dType] = value; + } + + _activeDTypes.Add(dType); + } + } + + // Return list of non-null DType mappings + public ItemStructList ActiveDTypes + { + get { return _activeDTypes; } + } + + // Clear the data-structures to be able to start over + public void Clear() + { + for (int i=0; i<_entryCount; i++) + { + _entries[i] = null; + } + + for (int i=0; i<_activeDTypes.Count; i++) + { + _activeDTypes.List[i] = null; + } + + if (_overFlow != null) + { + _overFlow.Clear(); + } + } + + private int _entryCount; + private object[] _entries; + private Hashtable _overFlow; + private ItemStructList _activeDTypes; + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/PerfService.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/PerfService.cs new file mode 100644 index 00000000000..5eba581e997 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/PerfService.cs @@ -0,0 +1,78 @@ +//--------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// +// Description: Implements the Service class for perf diagnostics +//--------------------------------------------------------------------------- + +using System; +using System.Text; +using System.Windows; +using System.Collections.Generic; +using SRCS = System.Runtime.CompilerServices; + +using Microsoft.Win32; +using MS.Internal.PresentationCore; +using MS.Internal; +using MS.Utility; +using MS.Win32.PresentationCore; +using System.Reflection; + +namespace MS.Utility +{ + [FriendAccessAllowed] + static internal class PerfService + { + // Map of elements to IDs. A couple of notes: + // 1) Use a ConditionalWeakTable because it holds weak references to + // the keys and is self-cleaning. + // 2) Use object, instead of long, for the values because + // ConditionalWeakTable requires the TValue parameter to be a + // reference type. + private static SRCS.ConditionalWeakTable perfElementIds = new SRCS.ConditionalWeakTable(); + + /// + /// Every element is uniquely identfied with an ID, and this ID + /// gets traced with ETW traces and can be mapped back to an + /// element in a tool. + /// + internal static long GetPerfElementID2(object element, string extraData) + { + return (long) perfElementIds.GetValue( + element, + delegate(object key) + { + long eltId = SafeNativeMethods.GetNextPerfElementId(); + + // If this is the first time we see this object emit some useful info about it. + if (EventTrace.IsEnabled(EventTrace.Keyword.KeywordGeneral, EventTrace.Level.Verbose)) + { + Type type = key.GetType(); + Assembly asm = type.Assembly; + + // Eventtracing below does a recursive call to GetPerfElementID2. + // Break the recustion by not tracing if key matches with asm. + if (!Object.ReferenceEquals(key, asm)) + { + EventTrace.EventProvider.TraceEvent( + EventTrace.Event.PerfElementIDAssignment, + EventTrace.Keyword.KeywordGeneral, + EventTrace.Level.Verbose, + eltId, + type.FullName, + extraData, + GetPerfElementID2(asm, asm.FullName)); + } + } + + return eltId; + }); + } + + internal static long GetPerfElementID(object element) + { + return GetPerfElementID2(element, string.Empty); + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/Trace.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/Trace.cs new file mode 100644 index 00000000000..de1da3ab51a --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/Trace.cs @@ -0,0 +1,169 @@ +/***************************************************************************\ +* +* File: Trace.cs +* +* Description: +* Implements ETW tracing for Avalon Managed Code +* +* Copyright (C) 2001 by Microsoft Corporation. All rights reserved. +* +\***************************************************************************/ +#if !SILVERLIGHTXAML + +using System.Collections; +using System.Diagnostics.Tracing; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Security.Permissions; +using System.Security; +using System.Threading; +using System; +using MS.Internal.WindowsBase; + + +#if SYSTEM_XAML +namespace MS.Internal.Xaml +#else +namespace MS.Utility +#endif +{ + #region Trace + + static internal partial class EventTrace + { + static readonly internal TraceProvider EventProvider; + + // EasyTraceEvent + // Checks the keyword and level before emiting the event + static internal void EasyTraceEvent(Keyword keywords, Event eventID) + { + if (IsEnabled(keywords, Level.Info)) + { + EventProvider.TraceEvent(eventID, keywords, Level.Info); + } + } + + // EasyTraceEvent + // Checks the keyword and level before emiting the event + static internal void EasyTraceEvent(Keyword keywords, Level level, Event eventID) + { + if (IsEnabled(keywords, level)) + { + EventProvider.TraceEvent(eventID, keywords, level); + } + } + + // EasyTraceEvent + // Checks the keyword and level before emiting the event + static internal void EasyTraceEvent(Keyword keywords, Event eventID, object param1) + { + if (IsEnabled(keywords, Level.Info)) + { + EventProvider.TraceEvent(eventID, keywords, Level.Info, param1); + } + } + + // EasyTraceEvent + // Checks the keyword and level before emiting the event + static internal void EasyTraceEvent(Keyword keywords, Level level, Event eventID, object param1) + { + if (IsEnabled(keywords, level)) + { + EventProvider.TraceEvent(eventID, keywords, level, param1); + } + } + + // EasyTraceEvent + // Checks the keyword and level before emiting the event + static internal void EasyTraceEvent(Keyword keywords, Event eventID, object param1, object param2) + { + if (IsEnabled(keywords, Level.Info)) + { + EventProvider.TraceEvent(eventID, keywords, Level.Info, param1, param2); + } + } + + static internal void EasyTraceEvent(Keyword keywords, Level level, Event eventID, object param1, object param2) + { + if (IsEnabled(keywords, Level.Info)) + { + EventProvider.TraceEvent(eventID, keywords, Level.Info, param1, param2); + } + } + + // EasyTraceEvent + // Checks the keyword and level before emiting the event + static internal void EasyTraceEvent(Keyword keywords, Event eventID, object param1, object param2, object param3) + { + if (IsEnabled(keywords, Level.Info)) + { + EventProvider.TraceEvent(eventID, keywords, Level.Info, param1, param2, param3); + } + } + + #region Trace related enumerations + + public enum LayoutSource : byte + { + LayoutManager, + HwndSource_SetLayoutSize, + HwndSource_WMSIZE + } + + #endregion + + /// + /// Callers use this to check if they should be logging. + /// + static internal bool IsEnabled(Keyword flag, Level level) + { + return EventProvider.IsEnabled(flag, level); + } + + /// + /// Internal operations associated with initializing the event provider and + /// monitoring the Dispatcher and input components. + /// + /// + /// Critical: This calls critical code in TraceProvider + /// TreatAsSafe: it generates the GUID that is passed into the TraceProvider + /// WPF versions prior to 4.0 used provider guid: {a42c77db-874f-422e-9b44-6d89fe2bd3e5} + /// + [SecurityCritical, SecurityTreatAsSafe] + static EventTrace() + { + Guid providerGuid = new Guid("E13B77A8-14B6-11DE-8069-001B212B5009"); + + if (Environment.OSVersion.Version.Major < 6 || + IsClassicETWRegistryEnabled()) + { + EventProvider = new ClassicTraceProvider(); + } + else + { + EventProvider = new ManifestTraceProvider(); + } + EventProvider.Register(providerGuid); + } + + [SecurityCritical] + static bool IsClassicETWRegistryEnabled() + { + try + { + string regKey = @"HKEY_CURRENT_USER\Software\Microsoft\Avalon.Graphics\"; + new RegistryPermission(RegistryPermissionAccess.Read, regKey).Assert(); + + return int.Equals(1, Microsoft.Win32.Registry.GetValue(regKey, "ClassicETW", 0)); + } + finally + { + RegistryPermission.RevertAssert(); + } + } + } + + #endregion Trace + +} +#endif diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/TraceProvider.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/TraceProvider.cs new file mode 100644 index 00000000000..c8845dd6da2 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/TraceProvider.cs @@ -0,0 +1,645 @@ +//--------------------------------------------------------------------------- +// File: TraceProvider +// +// A Managed wrapper for Event Tracing for Windows +// Based on TraceEvent.cs found in nt\base\wmi\trace.net +// Provides an internal Avalon API to replace Microsoft.Windows.EventTracing.dll +// +//--------------------------------------------------------------------------- +#if !SILVERLIGHTXAML +using System; +using MS.Win32; +using MS.Internal; +using System.Runtime.InteropServices; +using System.Security; +using System.Globalization; //for CultureInfo +using System.Diagnostics; +using MS.Internal.WindowsBase; + +#pragma warning disable 1634, 1691 //disable warnings about unknown pragma + +#if SYSTEM_XAML +using System.Xaml; +namespace MS.Internal.Xaml +#else +namespace MS.Utility +#endif +{ + [StructLayout(LayoutKind.Explicit, Size = 16)] + internal struct EventData + { + [FieldOffset(0)] + internal unsafe ulong Ptr; + [FieldOffset(8)] + internal uint Size; + [FieldOffset(12)] + internal uint Reserved; + } + + internal abstract class TraceProvider + { + protected bool _enabled = false; + protected EventTrace.Level _level = EventTrace.Level.LogAlways; + protected EventTrace.Keyword _keywords = (EventTrace.Keyword)0; /* aka Flags */ + protected EventTrace.Keyword _matchAllKeyword = (EventTrace.Keyword)0; /*Vista only*/ + protected SecurityCriticalDataForSet _registrationHandle; + + private const int s_basicTypeAllocationBufferSize = sizeof(decimal); + private const int s_traceEventMaximumSize = 65482; // maximum buffer size is 64k - header size + private const int s_etwMaxNumberArguments = 32; + private const int s_etwAPIMaxStringCount = 8; // Arbitrary limit on the number of strings you can emit. This is just to limit allocations so raise it if necessary. + private const int ErrorEventTooBig = 2; + + + [SecurityCritical] + internal TraceProvider() + { + _registrationHandle = new SecurityCriticalDataForSet(0); + } + + [SecurityCritical] + internal abstract void Register(Guid providerGuid); + [SecurityCritical] + internal unsafe abstract uint EventWrite(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level, int argc, EventData* argv); + + internal uint TraceEvent(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level) + { + // Optimization for 0-1 arguments + return TraceEvent(eventID, keywords, level, (object)null); + } + + #region Properties and Structs + + // + // Properties + // + internal EventTrace.Keyword Keywords + { + get + { + return _keywords; + } + } + + internal EventTrace.Keyword MatchAllKeywords + { + get + { + return _matchAllKeyword; + } + } + + internal EventTrace.Level Level + { + get + { + return _level; + } + } + + #endregion + + internal bool IsEnabled(EventTrace.Keyword keyword, EventTrace.Level level) + { + return _enabled && + (level <= _level) && + (keyword & _keywords) != 0 && + (keyword & _matchAllKeyword) == _matchAllKeyword; + } + + // Optimization for 0-1 arguments + [SecurityCritical, SecurityTreatAsSafe] + internal unsafe uint TraceEvent(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level, object eventData) + { + // It is the responsibility of the caller to check that flags/keywords are enabled before calling this method + Debug.Assert(IsEnabled(keywords, level)); + + uint status = 0; + int argCount = 0; + + EventData userData; + userData.Size = 0; + string dataString = null; + byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize]; + + if (eventData != null) + { + dataString = EncodeObject(ref eventData, &userData, dataBuffer); + argCount = 1; + } + + if (userData.Size > s_traceEventMaximumSize) + { + return ErrorEventTooBig; + } + + if (dataString != null) + { + fixed(char* pdata = dataString) + { + userData.Ptr = (ulong)pdata; + status = EventWrite(eventID, keywords, level, argCount, &userData); + } + } + else + { + status = EventWrite(eventID, keywords, level, argCount, &userData); + } + + return status; + } + + [SecurityCritical, SecurityTreatAsSafe] + internal unsafe uint TraceEvent(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level, params object[] eventPayload) + { + // It is the responsibility of the caller to check that flags/keywords are enabled before calling this method + Debug.Assert(IsEnabled(keywords, level)); + + int argCount = eventPayload.Length; + + Debug.Assert(argCount <= s_etwMaxNumberArguments); + + uint totalEventSize = 0; + int stringIndex = 0; + int[] stringPosition = new int[s_etwAPIMaxStringCount]; + string [] dataString = new string[s_etwAPIMaxStringCount]; + EventData* userData = stackalloc EventData[argCount]; + EventData* userDataPtr = userData; + byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * argCount]; + byte* currentBuffer = dataBuffer; + + + for (int index = 0; index < argCount; index++) + { + if (eventPayload[index] != null) + { + string isString = EncodeObject(ref eventPayload[index], userDataPtr, currentBuffer); + currentBuffer += s_basicTypeAllocationBufferSize; + totalEventSize = userDataPtr->Size; + userDataPtr++; + if (isString != null) + { + Debug.Assert(stringIndex < s_etwAPIMaxStringCount); // need to increase string count or emit fewer strings + dataString[stringIndex] = isString; + stringPosition[stringIndex] = index; + stringIndex++; + } + } + } + + if (totalEventSize > s_traceEventMaximumSize) + { + return ErrorEventTooBig; + } + + fixed(char* s0 = dataString[0], s1 = dataString[1], s2 = dataString[2], s3 = dataString[3], + s4 = dataString[4], s5 = dataString[5], s6 = dataString[6], s7 = dataString[7]) + { + userDataPtr = userData; + if (dataString[0] != null) + { + userDataPtr[stringPosition[0]].Ptr = (ulong)s0; + } + if (dataString[1] != null) + { + userDataPtr[stringPosition[1]].Ptr = (ulong)s1; + } + if (dataString[2] != null) + { + userDataPtr[stringPosition[2]].Ptr = (ulong)s2; + } + if (dataString[3] != null) + { + userDataPtr[stringPosition[3]].Ptr = (ulong)s3; + } + if (dataString[4] != null) + { + userDataPtr[stringPosition[4]].Ptr = (ulong)s4; + } + if (dataString[5] != null) + { + userDataPtr[stringPosition[5]].Ptr = (ulong)s5; + } + if (dataString[6] != null) + { + userDataPtr[stringPosition[6]].Ptr = (ulong)s6; + } + if (dataString[7] != null) + { + userDataPtr[stringPosition[7]].Ptr = (ulong)s7; + } + + return EventWrite(eventID, keywords, level, argCount, userData); + } + } + + + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + [SecurityCritical] + private static unsafe string EncodeObject(ref object data, EventData* dataDescriptor, byte* dataBuffer) + /*++ + + Routine Description: + + This routine is used by WriteEvent to unbox the object type and + to fill the passed in ETW data descriptor. + + Arguments: + + data - argument to be decoded + + dataDescriptor - pointer to the descriptor to be filled + + dataBuffer - storage buffer for storing user data, needed because cant get the address of the object + + Return Value: + + null if the object is a basic type other than string. String otherwise + + --*/ + { + dataDescriptor->Reserved = 0; + + string sRet = data as string; + if (sRet != null) + { + dataDescriptor->Size = (uint)((sRet.Length + 1) * 2); + return sRet; + } + + // If the data is an enum we'll convert it to it's underlying type + Type dataType = data.GetType(); + if (dataType.IsEnum) + { + data = Convert.ChangeType(data, Enum.GetUnderlyingType(dataType), CultureInfo.InvariantCulture); + } + + if (data is IntPtr) + { + dataDescriptor->Size = (uint)sizeof(IntPtr); + IntPtr* intptrPtr = (IntPtr*)dataBuffer; + *intptrPtr = (IntPtr)data; + dataDescriptor->Ptr = (ulong)intptrPtr; + } + else if (data is int) + { + dataDescriptor->Size = (uint)sizeof(int); + int* intptrPtr = (int*)dataBuffer; + *intptrPtr = (int)data; + dataDescriptor->Ptr = (ulong)intptrPtr; + } + else if (data is long) + { + dataDescriptor->Size = (uint)sizeof(long); + long* longptr = (long*)dataBuffer; + *longptr = (long)data; + dataDescriptor->Ptr = (ulong)longptr; + } + else if (data is uint) + { + dataDescriptor->Size = (uint)sizeof(uint); + uint* uintptr = (uint*)dataBuffer; + *uintptr = (uint)data; + dataDescriptor->Ptr = (ulong)uintptr; + } + else if (data is UInt64) + { + dataDescriptor->Size = (uint)sizeof(ulong); + ulong* ulongptr = (ulong*)dataBuffer; + *ulongptr = (ulong)data; + dataDescriptor->Ptr = (ulong)ulongptr; + } + else if (data is char) + { + dataDescriptor->Size = (uint)sizeof(char); + char* charptr = (char*)dataBuffer; + *charptr = (char)data; + dataDescriptor->Ptr = (ulong)charptr; + } + else if (data is byte) + { + dataDescriptor->Size = (uint)sizeof(byte); + byte* byteptr = (byte*)dataBuffer; + *byteptr = (byte)data; + dataDescriptor->Ptr = (ulong)byteptr; + } + else if (data is short) + { + dataDescriptor->Size = (uint)sizeof(short); + short* shortptr = (short*)dataBuffer; + *shortptr = (short)data; + dataDescriptor->Ptr = (ulong)shortptr; + } + else if (data is sbyte) + { + dataDescriptor->Size = (uint)sizeof(sbyte); + sbyte* sbyteptr = (sbyte*)dataBuffer; + *sbyteptr = (sbyte)data; + dataDescriptor->Ptr = (ulong)sbyteptr; + } + else if (data is ushort) + { + dataDescriptor->Size = (uint)sizeof(ushort); + ushort* ushortptr = (ushort*)dataBuffer; + *ushortptr = (ushort)data; + dataDescriptor->Ptr = (ulong)ushortptr; + } + else if (data is float) + { + dataDescriptor->Size = (uint)sizeof(float); + float* floatptr = (float*)dataBuffer; + *floatptr = (float)data; + dataDescriptor->Ptr = (ulong)floatptr; + } + else if (data is double) + { + dataDescriptor->Size = (uint)sizeof(double); + double* doubleptr = (double*)dataBuffer; + *doubleptr = (double)data; + dataDescriptor->Ptr = (ulong)doubleptr; + } + else if (data is bool) + { + dataDescriptor->Size = (uint)sizeof(bool); + bool* boolptr = (bool*)dataBuffer; + *boolptr = (bool)data; + dataDescriptor->Ptr = (ulong)boolptr; + } + else if (data is Guid) + { + dataDescriptor->Size = (uint)sizeof(Guid); + Guid* guidptr = (Guid*)dataBuffer; + *guidptr = (Guid)data; + dataDescriptor->Ptr = (ulong)guidptr; + } + else if (data is decimal) + { + dataDescriptor->Size = (uint)sizeof(decimal); + decimal* decimalptr = (decimal*)dataBuffer; + *decimalptr = (decimal)data; + dataDescriptor->Ptr = (ulong)decimalptr; + } + else if (data is Boolean) + { + dataDescriptor->Size = (uint)sizeof(Boolean); + Boolean* booleanptr = (Boolean*)dataBuffer; + *booleanptr = (Boolean)data; + dataDescriptor->Ptr = (ulong)booleanptr; + } + else + { + //To our eyes, everything else is a just a string + sRet = data.ToString(); + dataDescriptor->Size = (uint)((sRet.Length + 1) * 2); + return sRet; + } + + return null; + } + } + + // XP + internal sealed class ClassicTraceProvider : TraceProvider + { + private ulong _traceHandle = 0; + + /// + /// Critical - Field for critical type ClassicEtw.ControlCallback. + /// + [SecurityCritical] + private static ClassicEtw.ControlCallback _etwProc; // Trace Callback function + + [SecurityCritical] + internal ClassicTraceProvider() + { + } + + // + // Registers the providerGuid with an inbuilt callback + // + /// + /// Critical: This calls critical code in UnsafeNativeMethods.EtwTrace + /// and sets critical for set field _registrationHandle and _etwProc + /// + [SecurityCritical] + internal override unsafe void Register(Guid providerGuid) + { + ulong registrationHandle; + ClassicEtw.TRACE_GUID_REGISTRATION guidReg; + + Guid dummyGuid = new Guid(0xb4955bf0, + 0x3af1, + 0x4740, + 0xb4,0x75, + 0x99,0x05,0x5d,0x3f,0xe9,0xaa); + + _etwProc = new ClassicEtw.ControlCallback(EtwEnableCallback); + + // This dummyGuid is there for ETW backward compat issues and is the same for all downlevel trace providers + guidReg.Guid = &dummyGuid; + guidReg.RegHandle = null; + + ClassicEtw.RegisterTraceGuidsW(_etwProc, IntPtr.Zero, ref providerGuid, 1, ref guidReg, null, null, out registrationHandle); + _registrationHandle.Value = registrationHandle; + } + + // + // This callback function is called by ETW to enable or disable this provider + // + /// + /// Critical: This calls critical code in ClassicEtw + /// + [SecurityCritical] + private unsafe uint EtwEnableCallback(ClassicEtw.WMIDPREQUESTCODE requestCode, IntPtr context, IntPtr bufferSize, ClassicEtw.WNODE_HEADER* buffer) + { + try + { + switch (requestCode) + { + case ClassicEtw.WMIDPREQUESTCODE.EnableEvents: + _traceHandle = buffer->HistoricalContext; + _keywords = (EventTrace.Keyword)ClassicEtw.GetTraceEnableFlags((ulong)buffer->HistoricalContext); + _level = (EventTrace.Level)ClassicEtw.GetTraceEnableLevel((ulong)buffer->HistoricalContext); + _enabled = true; + break; + case ClassicEtw.WMIDPREQUESTCODE.DisableEvents: + _enabled = false; + _traceHandle = 0; + _level = EventTrace.Level.LogAlways; + _keywords = 0; + break; + default: + _enabled = false; + _traceHandle = 0; + break; + } + return 0; + } + catch(Exception e) + { + if (CriticalExceptions.IsCriticalException(e)) + { + throw; + } + else + { + return 0; + } + } + } + + /// + /// Critical: This calls critical code in EtwTrace + /// TreatAsSafe: the registration handle this passes in to UnregisterTraceGuids + /// was generated by the ETW unmanaged API and can't be tampered with from our side + /// + [SecurityCritical, SecurityTreatAsSafe] + ~ClassicTraceProvider() + { + #pragma warning suppress 6031 //presharp suppression + ClassicEtw.UnregisterTraceGuids(_registrationHandle.Value); + } + + // pack the argv data and emit the event using TraceEvent + [SecurityCritical] + internal unsafe override uint EventWrite(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level, int argc, EventData* argv) + { + ClassicEtw.EVENT_HEADER header; + header.Header.ClientContext = 0; + header.Header.Flags = ClassicEtw.WNODE_FLAG_TRACED_GUID | ClassicEtw.WNODE_FLAG_USE_MOF_PTR; + header.Header.Guid = EventTrace.GetGuidForEvent(eventID); + header.Header.Level = (byte)level; + header.Header.Type = (byte)EventTrace.GetOpcodeForEvent(eventID); + header.Header.Version = (ushort)EventTrace.GetVersionForEvent(eventID); + // Extra copy on XP to move argv to the end of the EVENT_HEADER + EventData* eventData = &header.Data; + + if (argc > ClassicEtw.MAX_MOF_FIELDS) + { + // Data will be lost on XP + argc = ClassicEtw.MAX_MOF_FIELDS; + } + + header.Header.Size = (ushort) (argc * sizeof(EventData) + 48); + for (int x = 0; x < argc; x++) + { + eventData[x].Ptr = argv[x].Ptr; + eventData[x].Size = argv[x].Size; + } + + return ClassicEtw.TraceEvent(_traceHandle, &header); + } + } + + // Vista and above + internal class ManifestTraceProvider : TraceProvider + { + /// + /// Critical - Field for critical type ManifestEtw.EtwEnableCallback. + /// + [SecurityCritical] + private static ManifestEtw.EtwEnableCallback _etwEnabledCallback; + + [SecurityCritical] + internal ManifestTraceProvider() + { + } + + /// + /// Critical - Sets critical _etwEnabledCallback field + /// - Calls critical ManifestEtw.EventRegister + /// + [SecurityCritical] + internal unsafe override void Register(Guid providerGuid) + { + _etwEnabledCallback =new ManifestEtw.EtwEnableCallback(EtwEnableCallback); + ulong registrationHandle = 0; + ManifestEtw.EventRegister(ref providerGuid, _etwEnabledCallback, null, ref registrationHandle); + _registrationHandle.Value = registrationHandle; + } + + /// + /// Critical - Accepts untrusted pointer argument + /// + [SecurityCritical] + private unsafe void EtwEnableCallback(ref Guid sourceId, int isEnabled, byte level, long matchAnyKeywords, long matchAllKeywords, ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, void* callbackContext) + { + _enabled = isEnabled > 0; + _level = (EventTrace.Level)level; + _keywords = (EventTrace.Keyword) matchAnyKeywords; + _matchAllKeyword = (EventTrace.Keyword) matchAllKeywords; + + // todo: parse data from EVENT_FILTER_DESCRIPTOR - see CLR EventProvider::GetDataFromController + } + + /// + /// Critical - Calls critical ManifestEtw.EventUnregister + /// TreatAsSafe: Only critical code can create this resource, + /// and no input parameters are accepted to this method. + /// In fact, this method is not directly callable, but only as + /// part of the GC, and the GC ensures that no other rooted + /// objects are holding a reference. This method clears the + /// handle and skips future calls to unregister the event, which + /// protects against resurrection. + /// + [SecurityCritical, SecurityTreatAsSafe] + ~ManifestTraceProvider() + { + if(_registrationHandle.Value != 0) + { + try + { + ManifestEtw.EventUnregister(_registrationHandle.Value); + } + finally + { + _registrationHandle.Value = 0; + } + } + } + + /// + /// Critical - Accepts untrusted pointer argument + /// + [SecurityCritical] + internal unsafe override uint EventWrite(EventTrace.Event eventID, EventTrace.Keyword keywords, EventTrace.Level level, int argc, EventData* argv) + { + ManifestEtw.EventDescriptor eventDescriptor; + eventDescriptor.Id = (ushort) eventID; + eventDescriptor.Version = EventTrace.GetVersionForEvent(eventID); + eventDescriptor.Channel = 0x10; // Since Channel isn't supported on XP we only use a single default channel. + eventDescriptor.Level = (byte)level; + eventDescriptor.Opcode = EventTrace.GetOpcodeForEvent(eventID); + eventDescriptor.Task = EventTrace.GetTaskForEvent(eventID); + eventDescriptor.Keywords = (long)keywords; + if (argc == 0) + { + argv = null; + } + + return ManifestEtw.EventWrite(_registrationHandle.Value, ref eventDescriptor, (uint)argc, argv); + } + + } +} + +#endif diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/ExternDll.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/ExternDll.cs new file mode 100644 index 00000000000..40fdf18ced6 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/ExternDll.cs @@ -0,0 +1,51 @@ + +using System; +namespace MS.Win32 +{ + internal static class ExternDll + { + public const string Activeds = "activeds.dll"; + public const string Advapi32 = "advapi32.dll"; + public const string Comctl32 = "comctl32.dll"; + public const string Comdlg32 = "comdlg32.dll"; + public const string DwmAPI = "dwmapi.dll"; + public const string Gdi32 = "gdi32.dll"; + public const string Gdiplus = "gdiplus.dll"; + public const string Hhctrl = "hhctrl.ocx"; + public const string Imm32 = "imm32.dll"; + public const string Kernel32 = "kernel32.dll"; + public const string Loadperf = "Loadperf.dll"; + public const string Mqrt = "mqrt.dll"; + public const string Mscoree = "mscoree.dll"; + public const string MsDrm = "msdrm.dll"; + public const string Mshwgst = "mshwgst.dll"; + public const string Msi = "msi.dll"; + public const string NaturalLanguage6 = "naturallanguage6.dll"; + public const string Ntdll = "ntdll.dll"; + public const string Ole32 = "ole32.dll"; + public const string Oleacc = "oleacc.dll"; + public const string Oleaut32 = "oleaut32.dll"; + public const string Olepro32 = "olepro32.dll"; + public const string Penimc ="PenIMC_cor3.dll"; + public const string PresentationCore = "PresentationCore.dll"; + public const string PresentationFramework = "PresentationFramework.dll"; + public const string PresentationHostDll = "PresentationHost_cor3.dll"; + public const string PresentationNativeDll = "PresentationNative_cor3.dll"; + public const string Psapi = "psapi.dll"; + public const string Shcore = "shcore.dll"; + public const string Shell32 = "shell32.dll"; + public const string Shfolder = "shfolder.dll"; + public const string Urlmon = "urlmon.dll"; + public const string User32 = "user32.dll"; + public const string Uxtheme = "uxtheme.dll"; + public const string Version = "version.dll"; + public const string Vsassert = "vsassert.dll"; + public const string WindowsBase = "windowsbase.dll"; + public const string Wininet = "wininet.dll"; + public const string Winmm = "winmm.dll"; + public const string Winspool = "winspool.drv"; + public const string WpfGfx = "WpfGfx_cor3.dll"; + public const string WtsApi32 = "wtsapi32.dll"; + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HandleCollector.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HandleCollector.cs new file mode 100644 index 00000000000..6d658ab8ce0 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HandleCollector.cs @@ -0,0 +1,184 @@ +using System; +using MS.Win32 ; +using System.Runtime.InteropServices; + +namespace MS.Win32 +{ + internal static class HandleCollector + { + private static HandleType[] handleTypes; + private static int handleTypeCount = 0; + + private static Object handleMutex = new Object(); + + /// + /// Adds the given handle to the handle collector. This keeps the + /// handle on a "hot list" of objects that may need to be garbage + /// collected. + /// + internal static IntPtr Add(IntPtr handle, int type) { + handleTypes[type - 1].Add(); + return handle; + } + + /// + /// Critical - Accepts and returns critical SafeHandle type. + /// Safe - Does not perform operations on the critical handle, does not leak handle information. + /// + [System.Security.SecuritySafeCritical] + internal static SafeHandle Add(SafeHandle handle, int type) { + handleTypes[type - 1].Add(); + return handle; + } + + internal static void Add(int type) { + handleTypes[type - 1].Add(); + } + + /// + /// Registers a new type of handle with the handle collector. + /// + internal static int RegisterType(string typeName, int expense, int initialThreshold) { + lock (handleMutex) + { + if (handleTypeCount == 0 || handleTypeCount == handleTypes.Length) + { + HandleType[] newTypes = new HandleType[handleTypeCount + 10]; + if (handleTypes != null) { + Array.Copy(handleTypes, 0, newTypes, 0, handleTypeCount); + } + handleTypes = newTypes; + } + + handleTypes[handleTypeCount++] = new HandleType(typeName, expense, initialThreshold); + return handleTypeCount; + } + } + + /// + /// Removes the given handle from the handle collector. Removing a + /// handle removes it from our "hot list" of objects that should be + /// frequently garbage collected. + /// + internal static IntPtr Remove(IntPtr handle, int type) { + handleTypes[type - 1].Remove(); + return handle ; + } + + /// + /// Critical - Accepts and returns critical SafeHandle type. + /// Safe - Does not perform operations on the critical handle, does not leak handle information. + /// + [System.Security.SecuritySafeCritical] + internal static SafeHandle Remove(SafeHandle handle, int type) { + handleTypes[type - 1].Remove(); + return handle ; + } + + internal static void Remove(int type) { + handleTypes[type - 1].Remove(); + } + + /// + /// Represents a specific type of handle. + /// + private class HandleType + { + internal readonly string name; + + private int initialThreshHold; + private int threshHold; + private int handleCount; + private readonly int deltaPercent; + + /// + /// Creates a new handle type. + /// + internal HandleType(string name, int expense, int initialThreshHold) { + this.name = name; + this.initialThreshHold = initialThreshHold; + this.threshHold = initialThreshHold; + this.deltaPercent = 100 - expense; + } + + /// + /// Adds a handle to this handle type for monitoring. + /// + internal void Add() { + bool performCollect = false; + + lock(this) { + handleCount++; + performCollect = NeedCollection(); + + if (!performCollect) { + return; + } + } + + if (performCollect) { +#if DEBUG_HANDLECOLLECTOR + Debug.WriteLine("HC> Forcing garbage collect"); + Debug.WriteLine("HC> name :" + name); + Debug.WriteLine("HC> threshHold :" + (threshHold).ToString()); + Debug.WriteLine("HC> handleCount :" + (handleCount).ToString()); + Debug.WriteLine("HC> deltaPercent:" + (deltaPercent).ToString()); +#endif + GC.Collect(); + + // We just performed a GC. If the main thread is in a tight + // loop there is a this will cause us to increase handles forever and prevent handle collector + // from doing its job. Yield the thread here. This won't totally cause + // a finalization pass but it will effectively elevate the priority + // of the finalizer thread just for an instant. But how long should + // we sleep? We base it on how expensive the handles are because the + // more expensive the handle, the more critical that it be reclaimed. + int sleep = (100 - deltaPercent) / 4; + System.Threading.Thread.Sleep(sleep); + } + } + + + /// + /// Determines if this handle type needs a garbage collection pass. + /// + internal bool NeedCollection() { + + if (handleCount > threshHold) { + threshHold = handleCount + ((handleCount * deltaPercent) / 100); +#if DEBUG_HANDLECOLLECTOR + Debug.WriteLine("HC> NeedCollection: increase threshHold to " + threshHold); +#endif + return true; + } + + // If handle count < threshHold, we don't + // need to collect, but if it 10% below the next lowest threshhold we + // will bump down a rung. We need to choose a percentage here or else + // we will oscillate. + // + int oldThreshHold = (100 * threshHold) / (100 + deltaPercent); + if (oldThreshHold >= initialThreshHold && handleCount < (int)(oldThreshHold * .9F)) { +#if DEBUG_HANDLECOLLECTOR + Debug.WriteLine("HC> NeedCollection: throttle threshhold " + threshHold + " down to " + oldThreshHold); +#endif + threshHold = oldThreshHold; + } + + return false; + } + + /// + /// Removes the given handle from our monitor list. + /// + internal void Remove() { + lock(this) { + handleCount--; + + handleCount = Math.Max(0, handleCount); + } + } + } + } + +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndSubclass.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndSubclass.cs new file mode 100644 index 00000000000..e72ef1c871d --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndSubclass.cs @@ -0,0 +1,742 @@ +using System; +using System.Runtime.InteropServices; +using System.Security.Permissions; +using MS.Internal; +using MS.Internal.Interop; +using MS.Utility; +using System.Windows; +using System.Windows.Threading; +using System.Security; // CAS +using System.Threading; // Thread + +// The SecurityHelper class differs between assemblies and could not actually be +// shared, so it is duplicated across namespaces to prevent name collision. +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif DRT + using MS.Internal.Drt; +#else +#error Attempt to use a class (duplicated across multiple namespaces) from an unknown assembly. +#endif + +namespace MS.Win32 +{ + /// + /// The HwndSubclass class provides a managed way to subclass an existing + /// HWND. This class inserts itself into the WNDPROC chain for the + /// window, and will call a specified delegate to process the window + /// messages that arrive. The delegate has a slightly different + /// signature than a WNDPROC to be more specific about whether the + /// message was handled or not. If the message was not handled by the + /// delegate, this class passes the message on down the WNDPROC chain. + /// + /// To use this class properly, simply: + /// 1) Create an instance of the HwndSubclass class and pass the delegate + /// to the constructor. + /// 2) Call Attach(HWND) to subclass an existing window. + /// 3) Call Detach(false) to unsubclass the window when you are done. + /// + /// You can also just call RequestDetach() to send a message to the + /// window that will cause the HwndSubclass to detach itself. This is + /// important if you are on a different thread, as the HwndSubclass class + /// is not thread safe and will be operated on by the thread that owns + /// the window. + /// + /// Not available to partial trust callers + [FriendAccessAllowed] // Built into Base, also used by Framework + internal class HwndSubclass : IDisposable + { + /// + /// Critical: Elevates by calling an UnsafeNativeMethod + /// + [SecurityCritical] + static HwndSubclass() + { + DetachMessage = UnsafeNativeMethods.RegisterWindowMessage("HwndSubclass.DetachMessage"); + + // Go find the address of DefWindowProc. + IntPtr hModuleUser32 = UnsafeNativeMethods.GetModuleHandle(ExternDll.User32); + IntPtr address = UnsafeNativeMethods.GetProcAddress(new HandleRef(null,hModuleUser32), "DefWindowProcW"); + + DefWndProc = address; + } + + /// + /// This HwndSubclass constructor binds the HwndSubclass object to the + /// specified delegate. This delegate will be called to process + /// the messages that are sent or posted to the window. + /// + /// + /// The delegate that will be called to process the messages that + /// are sent or posted to the window. + /// + /// + /// Nothing. + /// + /// + /// Critical: This code creates an object that is not allowed in partial trust + /// + [SecurityCritical] + internal HwndSubclass(HwndWrapperHook hook) + { + if(hook == null) + { + throw new ArgumentNullException("hook"); + } + + _bond = Bond.Unattached; + _hook = new WeakReference(hook); + + // Allocate a GC handle so that we won't be collected, even if all + // references to us get released. This is because a component outside + // of the managed code (ie. the window we are subclassing) still holds + // a reference to us - just not a reference that the GC recognizes. + _gcHandle = GCHandle.Alloc(this); + } + + // This is LIVE OBJECT because it has a GCHandle. The only time LIVE OBJECTS + // are destroyed is during Shutdown. But Shutdown cleanup is handled through + // the ManagedWndProcTracker and hence no work needs to happen here. PLEASE + // NOTE that reintroducing any cleanup logic in here will conflict with the cleanup + // logic in ManagedWndProcTracker and hence must be avoided. If this instance + // has been disposed its GCHandle is released at the time and hence this object + // is available for GC thereafter. Even in that case since all the cleanup has been + // done during dispose there is no further cleanup required. + + // /// + // /// Critical - It calls the critical DisposeImpl. + // /// + // [SecurityCritical] + // ~HwndSubclass() + // { + // // In Shutdown, the finalizer is called on LIVE OBJECTS. + // // + // // So this method can be called. (even though we are pinned) + // // If it is, we're shutting down so it's OK to force unhooking + // // the subclass. + // DisposeImpl(true); + // } + + /// + /// Critical - It calls the critical DisposeImpl. + /// PublicOK - Demands for AllWindows permission. + /// + [SecurityCritical] + public virtual void Dispose() + { + SecurityHelper.DemandUIWindowPermission(); + + DisposeImpl(false); + } + + /// + /// Critical - Calls the critical UnhookWindowProc. + /// + [SecurityCritical] + private bool DisposeImpl(bool forceUnhook) + { + _hook = null; + + return UnhookWindowProc(forceUnhook); + } + + /// + /// This method subclasses the specified window, such that the + /// delegate specified to the constructor will be called to process + /// the messages that are sent or posted to this window. + /// + /// + /// The window to subclass. + /// + /// + /// An identifier that can be used to reference this instance of + /// the HwndSubclass class in the static RequestDetach method. + /// + /// + /// Critical - It calls CriticalAttach. + /// TreatAsSafe - Demands for AllWindows permission. + /// + [SecurityCritical, SecurityTreatAsSafe] + internal IntPtr Attach(IntPtr hwnd) + { + SecurityHelper.DemandUIWindowPermission(); + + if (_bond != Bond.Unattached) + throw new InvalidOperationException(SR.Get(SRID.HwndSubclassMultipleAttach)); + + return CriticalAttach( hwnd ) ; + } + + + /// + /// This method unsubclasses this HwndSubclass object from the window + /// it previously subclassed. The HwndSubclass object is not thread + /// safe, and should thus be called only by the thread that owns + /// the window being unsubclassed. + /// + /// + /// Whether or not the unsubclassing should be forced. Due to the + /// way that Win32 implements window subclassing, it is not always + /// possible to safely remove a window proc from the WNDPROC chain. + /// However, the delegate will not be called again after this + /// method returns. + /// + /// + /// Whether or not this HwndSubclass object was actually removed from + /// the WNDPROC chain. + /// + /// + /// TreatAsSafe: Demands for all windows + /// Critical: Elevates by calling an UnsafeNativeMethod + /// + [SecurityCritical] + internal bool Detach(bool force) + { + SecurityHelper.DemandUIWindowPermission(); + + return CriticalDetach(force); + } + + /// + /// Critical: Elevates by calling an UnsafeNativeMethod + /// + [SecurityCritical] + internal bool CriticalDetach(bool force) + { + bool detached; + + // If we have already detached, return immediately. + if(_bond == Bond.Detached || _bond == Bond.Unattached) + { + detached = true; + } + else + { + // When we detach, we simply make a note of it. + _bond = Bond.Orphaned; + + // try to unhook the subclass + detached = DisposeImpl(force); + } + + return detached; + } + + /// + /// This method sends a message to the window that is currently + /// subclassed by this instance of the HwndSubclass class, in order + /// to unsubclass the window. This is important if a different + /// thread than the thread that owns the window wants to initiate + /// the unsubclassing. + /// + /// + /// Whether or not the unsubclassing should be forced. Due to the + /// way that Win32 implements window subclassing, it is not always + /// possible to safely remove a window proc from the WNDPROC chain. + /// However, the delegate will not be called again after this + /// method returns. + /// + /// + /// Nothing. + /// + /// + /// Critical - Probes _hwndAttached for value. + /// TreatAsSafe - The RequestDetach overload we're calling is public and safe (demands UIWindowPermission). + /// + [SecurityCritical, SecurityTreatAsSafe] + internal void RequestDetach(bool force) + { + // Let the static version do the work. + if(_hwndAttached != IntPtr.Zero) + { + RequestDetach(_hwndAttached, (IntPtr) _gcHandle, force); + } + } + + /// + /// This method sends a message to the specified window in order to + /// cause the specified bridge to unsubclass the window. This is + /// important if a different thread than the thread that owns the + /// window wants to initiate the unsubclassing. The HwndSubclass + /// object must be identified by the value returned from Attach(). + /// + /// + /// The window to unsubclass. + /// + /// + /// The identifier of the subclass to unsubclass. + /// + /// + /// Whether or not the unsubclassing should be forced. Due to the + /// way that Win32 implements window subclassing, it is not always + /// possible to safely remove a window proc from the WNDPROC chain. + /// However, the delegate will not be called again after this + /// method returns. + /// + /// + /// Nothing. + /// + /// + /// Critical - This touches the underlying windowing infrastructure; we may want to intercept windows-messages for security-related purposes in the future. + /// In general we restrict access to window handles. + /// TreatAsSafe - Demands UIWindowPermission. + /// + [SecurityCritical, SecurityTreatAsSafe] + internal static void RequestDetach(IntPtr hwnd, IntPtr subclass, bool force) + { + SecurityHelper.DemandUIWindowPermission(); + if(hwnd == IntPtr.Zero) + { + throw new ArgumentNullException("hwnd"); + } + if(subclass == IntPtr.Zero) + { + throw new ArgumentNullException("subclass"); + } + + int iForce = force ? 1 : 0; + UnsafeNativeMethods.UnsafeSendMessage(hwnd, DetachMessage, subclass, (IntPtr) iForce); + } + + /// + /// This is the WNDPROC that gets inserted into the window's + /// WNDPROC chain. It responds to various conditions that + /// would cause this HwndSubclass object to unsubclass the window, + /// and then calls the delegate specified to the HwndSubclass + /// constructor to process the message. If the delegate does not + /// handle the message, the message is then passed on down the + /// WNDPROC chain for further processing. + /// + /// + /// The window that this message was sent or posted to. + /// + /// + /// The message that was sent or posted. + /// + /// + /// A parameter for the message that was sent or posted. + /// + /// + /// A parameter for the message that was sent or posted. + /// + /// + /// The value that is the result of processing the message. + /// + /// + /// Critical: this function elevates via unsafe native method calls + /// + [SecurityCritical] + internal IntPtr SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) + { + IntPtr retval = IntPtr.Zero; + bool handled = false; + WindowMessage message = (WindowMessage)msg; + + // If we are unattached and we receive a message, then we must have + // been used as the original window proc. In this case, we insert + // ourselves as if the original window proc had been DefWindowProc. + // We pass in DefWndProcStub as a workaround for a bug in UxTheme on + // Windows XP. For details see the comment on the DefWndProcWrapper method. + if(_bond == Bond.Unattached) + { + HookWindowProc(hwnd, new NativeMethods.WndProc(SubclassWndProc), + Marshal.GetFunctionPointerForDelegate(DefWndProcStub)); + } + else if(_bond == Bond.Detached) + { + throw new InvalidOperationException(); + } + + IntPtr oldWndProc = _oldWndProc; // in case we get detached during this method + + if(message == DetachMessage) + { + // We received our special message to detach. Make sure it is intended + // for us by matching the bridge. + if(wParam == IntPtr.Zero || wParam == (IntPtr)_gcHandle) + { + int param = (int)lParam; // 0 - normal, 1 - force, 2 - force and forward + bool force = (param > 0); + + retval = CriticalDetach(force) ? new IntPtr(1) : IntPtr.Zero ; + handled = (param < 2); + } + } + else + { + // Pass this message to our delegate function. Do this under + // the exception filter/handlers of the dispatcher for this thread. + Dispatcher dispatcher = Dispatcher.FromThread(Thread.CurrentThread); + if(dispatcher != null && !dispatcher.HasShutdownFinished) + { + if (_dispatcherOperationCallback == null) + _dispatcherOperationCallback = new DispatcherOperationCallback(this.DispatcherCallbackOperation); + + // _paramDispatcherCallbackOperation is a thread static member which should be reused to avoid + // creating a new data structure every time we call DispatcherCallbackOperation + // Cache the param locally in case of reentrance and set _paramDispatcherCallbackOperation to null so reentrancy calls will create a new param + if (_paramDispatcherCallbackOperation == null) + _paramDispatcherCallbackOperation = new DispatcherOperationCallbackParameter(); + + DispatcherOperationCallbackParameter param = _paramDispatcherCallbackOperation; + _paramDispatcherCallbackOperation = null; + param.hwnd = hwnd; + param.msg = msg; + param.wParam = wParam; + param.lParam = lParam; + //synchronous call + object result = dispatcher.Invoke( + DispatcherPriority.Send, + _dispatcherOperationCallback, + param); + + + if (result != null) + { + handled = param.handled; + retval = param.retVal; + } + + // Restore _paramDispatcherCallbackOperation to the previous value so we will reuse it on the next call + _paramDispatcherCallbackOperation = param; + } + + // Handle WM_NCDESTROY explicitly to forcibly clean up. + if(message == WindowMessage.WM_NCDESTROY) + { + // The fact that we received this message means that we are + // still in the call chain. This is our last chance to clean + // up, and no other message should be received by this window + // proc again. It is OK to force a cleanup now. + CriticalDetach(true); + + // Always pass the WM_NCDESTROY message down the chain! + handled = false; + } + } + + // If our window proc didn't handle this message, pass it on down the + // chain. + if(!handled) + { + retval = CallOldWindowProc(oldWndProc, hwnd, message, wParam, lParam); + } + + return retval; + } + + // Perf bug: 1963989 + // _paramDispatcherCallbackOperation is a thread static member which should be reused to avoid + // creating a new data structure every time we DispatcherCallbackOperation is called + // It also contains the return results (handled and retValue) from DispatcherCallbackOperation call + /// + /// Critical: DispatcherOperationCallbackParameter contains hwnd, which is critical + /// + [SecurityCritical] + [ThreadStatic] + private static DispatcherOperationCallbackParameter _paramDispatcherCallbackOperation; + + // This class is used as a parameter and return result for DispatcherCallbackOperation call + private class DispatcherOperationCallbackParameter + { + internal IntPtr hwnd, wParam, lParam, retVal; + internal int msg; + internal bool handled; + } + + private DispatcherOperationCallback _dispatcherOperationCallback = null; + + /// + /// Critical: it calls GetWindowLongPtr(), which is Critical + /// + [ SecurityCritical ] + internal IntPtr CriticalAttach( IntPtr hwnd ) + { + if(hwnd == IntPtr.Zero) + { + throw new ArgumentNullException("hwnd"); + } + if(_bond != Bond.Unattached) + { + throw new InvalidOperationException(); + } + + NativeMethods.WndProc newWndProc = new NativeMethods.WndProc(SubclassWndProc); + IntPtr oldWndProc = UnsafeNativeMethods.GetWindowLongPtr(new HandleRef(this,hwnd), NativeMethods.GWL_WNDPROC); + HookWindowProc(hwnd, newWndProc, oldWndProc); + + // Return the GC handle as a unique identifier of this + return (IntPtr) _gcHandle; + } + + /// + /// Critical: This code is a callback into the dispatcher. It is present + /// because under enforcements anonymous delagates throw a demand since + /// it becomes a transparent calling critical for this particular call + /// + [SecurityCritical] + private object DispatcherCallbackOperation(object o) + { + DispatcherOperationCallbackParameter param = (DispatcherOperationCallbackParameter)o; + param.handled = false; + param.retVal = IntPtr.Zero; + if (_bond == Bond.Attached) + { + HwndWrapperHook hook= _hook.Target as HwndWrapperHook; + + if (hook != null) + { + // make the call + param.retVal = hook(param.hwnd, param.msg, param.wParam, param.lParam, ref param.handled); + } + } + + return param; + } + + /// + /// This method lets the user call the old WNDPROC, i.e + /// the next WNDPROC in the chain directly. + /// + /// + /// The WndProc to call. + /// + /// + /// The window that this message was sent or posted to. + /// + /// + /// The message that was sent or posted. + /// + /// + /// A parameter for the message that was sent or posted. + /// + /// + /// A parameter for the message that was sent or posted. + /// + /// + /// The value that is the result of processing the message. + /// + /// + /// Critical: Elevates by calling an UnsafeNativeMethod + /// + [SecurityCritical] + IntPtr CallOldWindowProc(IntPtr oldWndProc, IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam) + { + return UnsafeNativeMethods.CallWindowProc(oldWndProc, hwnd, (int)msg, wParam, lParam); + } + + /// + /// Critical - it calls CriticalSetWindowLong() + /// + [SecurityCritical] + private void HookWindowProc(IntPtr hwnd, NativeMethods.WndProc newWndProc, IntPtr oldWndProc) + { + _hwndAttached = hwnd; + _hwndHandleRef = new HandleRef(null,_hwndAttached); + _bond = Bond.Attached; + + _attachedWndProc = newWndProc; + _oldWndProc = oldWndProc; + IntPtr oldWndProc2 = (IntPtr)UnsafeNativeMethods.CriticalSetWindowLong(_hwndHandleRef, NativeMethods.GWL_WNDPROC, _attachedWndProc); + + // Track this window so that we can rip out the managed window proc + // when the CLR shuts down. + ManagedWndProcTracker.TrackHwndSubclass(this, _hwndAttached); + } + + // This method should only be called from Dispose. Otherwise assumptions about the disposing/finalize state could be violated. + // force - when true, remove this subclass from the WndProc chain regardless of + // its current position. When false, remove this subclass only + // if it is possible to do so without damaging other WndProcs + // (i.e. only if this is at the head of the chain). + // + // Removing this subclass from the WndProc chain when it is not at the head + // also removes all other WndProcs that appear before this one on the chain, + // so is generally not appropriate. It is OK in the following situations: + // a) in response to the WM_NCDESTROY message + // b) in response to the AppDomainProcessExit event + // c) in response to the AppDomainExit event + // In cases (a) and (b) the HWND is being destroyed, so the earlier + // WndProcs are no longer useful anyway. In case (c), we have to remove + // all managed code from the chain lest it be called after it has been + // removed from memory; removing earlier WndProcs is unfortunate, but + // necessary. [Note that at AppDomainExit we remove all managed WndProcs, + // regardless of which AppDomain they came from. There is room for + // improvement here - we could remove only the ones belong to the AppDomain + // that is exiting. This situation seems too unlikely to worry about in V1.] + // + // This method returns true if the subclass is no longer in the WndProc chain. + // + /// + /// Critical - Calls CriticalSetWindowLong() and GetWindowLongWndProc(). + /// This touches the underlying windowing infrastructure; we may want to intercept windows-messages for security-related purposes in the future. + /// In general we restrict access to window handles. + /// + [SecurityCritical] + private bool UnhookWindowProc(bool force) + { + // if we're not in the WndProc chain, there's nothing to do + if (_bond == Bond.Unattached || _bond == Bond.Detached) + { + return true; + } + + // we'll remove ourselves from the chain if we're at the head, or if + // the 'force' parameter was true. + if (!force) + { + NativeMethods.WndProc currentWndProc = UnsafeNativeMethods.GetWindowLongWndProc(new HandleRef(this,_hwndAttached)); + force = (currentWndProc == _attachedWndProc); + } + + // if we're not unhooking, return and report + if (!force) + { + return false; + } + + // unhook from the tracker + _bond = Bond.Orphaned; // ignore messages while we're unhooking + ManagedWndProcTracker.UnhookHwndSubclass(this); + + // unhook, the Win32 way + try + { + UnsafeNativeMethods.CriticalSetWindowLong(_hwndHandleRef, NativeMethods.GWL_WNDPROC, _oldWndProc); + } + catch (System.ComponentModel.Win32Exception e) + { + if (e.NativeErrorCode != 1400) // ERROR_INVALID_WINDOW_HANDLE + { + throw; + } + } + + + // clear our state + _bond = Bond.Detached; + + _oldWndProc = IntPtr.Zero; + _attachedWndProc = null; + _hwndAttached = IntPtr.Zero; + _hwndHandleRef = new HandleRef(null,IntPtr.Zero); + + // un-Pin this object. + // Note: the GC is free to collect this object at anytime + // after we have freed this handle - that is, once all + // other managed references go away. + + //AvDebug.Assert(_gcHandle.IsAllocated, "External GC handle has not been allocated."); + + if(null != _gcHandle) + _gcHandle.Free(); + + return true; + } + + + + + /// + /// DefWndProcWrapper is a wrapper around DefWndProc. This is a workaround + /// for WindowsSE bugs 124461 and 124455, which affect Windows XP SP2, Luna theme. + /// + /// HwndSubclass.SubclassWndProc is sometimes directly set as the window proc of a + /// Window (HwndWrapper's constructor does this). When this happens it subclasses + /// itself on the first message it receives. Since the old window proc is itself, + /// it saves off DefWndProc as the old window proc instead. + /// + /// As described by the bugs and and KB article 319740, if we set DefWndProc + /// as the window proc of the window, we'll leak 6 GDI region objects + /// corresponding to the Luna-themed non-client area. + /// + /// The reason for this is that the kernel will flag that window as a server-side + /// window. If the WndProc replacement happens in response to a WM_NCDESTROY message + /// (as it does in the case where Avalon is creating and closing windows), the Shell + /// won't clean up the regions. + /// + /// The fix is slated for XP SP3, so for now WPF is implementing a workaround: + /// if we set the window proc to be a stub that calls into DefWndProc, the kernel + /// won't set us as a server-side window. + /// + /// + /// Critical: Elevates by calling an UnsafeNativeMethod + /// + [SecurityCritical] + private static IntPtr DefWndProcWrapper(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) + { + return UnsafeNativeMethods.CallWindowProc(DefWndProc, hwnd, msg, wParam, lParam); + } + + + + // Message to cause a detach. + // WPARAM=IntPtr returned from Attach(), or 0 to match all subclasses. + // LPARAM= 0 - normal (unhook subclass if it is first on the chain) + // 1 - force unhooking subclass from the chain + // 2 - force, and forward message to next WndProc + internal static readonly WindowMessage DetachMessage; + + private enum Bond + { + Unattached, + Attached, + Detached, + Orphaned + } + + + /// + /// This is a delegate that points to DefWndProcWrapper. It is set into + /// a Window's WndProc instead of DefWndProc in order to work around a bug. + /// See the comment on DefWndProcWrapper. + /// + /// By instantiating this delegate as a static variable we ensure that + /// it will remain alive long enough to process messages. + /// + /// + /// Critical: This will expose DefWndProc + /// + [SecurityCritical] + private static NativeMethods.WndProc DefWndProcStub = new NativeMethods.WndProc(DefWndProcWrapper); + + /// + /// Critical: This will expose wndproc + /// + [SecurityCritical] + private static IntPtr DefWndProc; + + /// + /// Critical: This will expose the intptr of the window + /// + [SecurityCritical] + private IntPtr _hwndAttached; + /// + /// Critical: This will expose window handle + /// + [SecurityCritical] + private HandleRef _hwndHandleRef; + /// + /// Critical: This will expose wndproc + /// + [SecurityCritical] + private NativeMethods.WndProc _attachedWndProc; + /// + /// Critical: This will expose wndproc + /// + [SecurityCritical] + private IntPtr _oldWndProc; + private Bond _bond; + private GCHandle _gcHandle; + /// + /// Critical: This will expose hook + /// + [SecurityCritical] + private WeakReference _hook; + }; +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndWrapper.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndWrapper.cs new file mode 100644 index 00000000000..db3186fb80d --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndWrapper.cs @@ -0,0 +1,505 @@ +//------------------------------------------------------------------------------ +// Microsoft Avalon +// Copyright (c) Microsoft Corporation, 2004 +// +// File: HwndWrapper.cs +//------------------------------------------------------------------------------ +using System; +using System.Security; +using System.Security.Permissions; +using System.Collections.Generic; +using System.Threading; +using System.Windows.Threading; +using System.Runtime.InteropServices; +using System.Diagnostics; +using MS.Internal; +using MS.Internal.Interop; +using System.Globalization; // CultureInfo.InvariantCulture + +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif DRT + using MS.Internal.Drt; +#else +#error Attempt to use FriendAccessAllowedAttribute from an unknown assembly. +using MS.Internal.YourAssemblyName; +#endif + +// Disable pragma warnings to enable PREsharp pragmas +#pragma warning disable 1634, 1691 + +namespace MS.Win32 +{ + [FriendAccessAllowed] + internal class HwndWrapper : DispatcherObject, IDisposable + { + /// + /// SecurityCritical: uses UnsafeNativeMethods RegisterWindowMessage + /// SecurityTreatAsSafe: This is safe to call + /// + [SecurityCritical, SecurityTreatAsSafe] + static HwndWrapper() + { + s_msgGCMemory = UnsafeNativeMethods.RegisterWindowMessage("HwndWrapper.GetGCMemMessage"); + } + + /// + /// SecurityCritical: uses UnsafeNativeMethods GetModuleHandle + /// elevates to call HwndSubclass Dispose + /// sets critical _wndProc field + /// + [SecurityCritical] + public HwndWrapper( + int classStyle, + int style, + int exStyle, + int x, + int y, + int width, + int height, + string name, + IntPtr parent, + HwndWrapperHook[] hooks) + { + + _ownerThreadID = new SecurityCriticalDataForSet(Thread.CurrentThread.ManagedThreadId); + + + // First, add the set of hooks. This allows the hooks to receive the + // messages sent to the window very early in the process. + if(hooks != null) + { + for(int i = 0, iEnd = hooks.Length; i < iEnd; i++) + { + if(null != hooks[i]) + AddHook(hooks[i]); + } + } + + + _wndProc = new SecurityCriticalData(new HwndWrapperHook(WndProc)); + + // We create the HwndSubclass object so that we can use its + // window proc directly. We will not be "subclassing" the + // window we create. + HwndSubclass hwndSubclass = new HwndSubclass(_wndProc.Value); + + // Register a unique window class for this instance. + NativeMethods.WNDCLASSEX_D wc_d = new NativeMethods.WNDCLASSEX_D(); + + IntPtr hNullBrush = UnsafeNativeMethods.CriticalGetStockObject(NativeMethods.NULL_BRUSH); + + if (hNullBrush == IntPtr.Zero) + { + throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); + } + + IntPtr hInstance = UnsafeNativeMethods.GetModuleHandle( null ); + + // We need to keep the Delegate object alive through the call to CreateWindowEx(). + // Subclass.WndProc will install a better delegate (to the same function) when it + // processes the first message. + // But this first delegate needs be held alive until then. + NativeMethods.WndProc initialWndProc = new NativeMethods.WndProc(hwndSubclass.SubclassWndProc); + + // The class name is a concat of AppName, ThreadName, and RandomNumber. + // Register will fail if the string gets over 255 in length. + // So limit each part to a reasonable amount. + string appName; + if(null != AppDomain.CurrentDomain.FriendlyName && 128 <= AppDomain.CurrentDomain.FriendlyName.Length) + appName = AppDomain.CurrentDomain.FriendlyName.Substring(0, 128); + else + appName = AppDomain.CurrentDomain.FriendlyName; + + string threadName; + if(null != Thread.CurrentThread.Name && 64 <= Thread.CurrentThread.Name.Length) + threadName = Thread.CurrentThread.Name.Substring(0, 64); + else + threadName = Thread.CurrentThread.Name; + + // Create a suitable unique class name. + _classAtom = 0; + string randomName = Guid.NewGuid().ToString(); + string className = String.Format(CultureInfo.InvariantCulture, "HwndWrapper[{0};{1};{2}]", appName, threadName, randomName); + + wc_d.cbSize = Marshal.SizeOf(typeof(NativeMethods.WNDCLASSEX_D)); + wc_d.style = classStyle; + wc_d.lpfnWndProc = initialWndProc; + wc_d.cbClsExtra = 0; + wc_d.cbWndExtra = 0; + wc_d.hInstance = hInstance; + wc_d.hIcon = IntPtr.Zero; + wc_d.hCursor = IntPtr.Zero; + wc_d.hbrBackground = hNullBrush; + wc_d.lpszMenuName = ""; + wc_d.lpszClassName = className; + wc_d.hIconSm = IntPtr.Zero; + + // Register the unique class for this instance. + // Note we use a GUID in the name so we are confident that + // the class name should be unique. And RegisterClassEx won't + // fail (for that reason). + _classAtom = UnsafeNativeMethods.RegisterClassEx(wc_d); + + // call CreateWindow + _isInCreateWindow = true; + try { + _handle = new SecurityCriticalDataClass(UnsafeNativeMethods.CreateWindowEx(exStyle, + className, + name, + style, + x, + y, + width, + height, + new HandleRef(null,parent), + new HandleRef(null,IntPtr.Zero), + new HandleRef(null,IntPtr.Zero), + null)); + } + finally + { + _isInCreateWindow = false; + if(_handle == null || _handle.Value == IntPtr.Zero) + { + new UIPermission(UIPermissionWindow.AllWindows).Assert(); //BlessedAssert to call Dispose + try + { + // Because the HwndSubclass is pinned, but the HWND creation failed, + // we need to manually clean it up. + hwndSubclass.Dispose(); + } + finally + { + CodeAccessPermission.RevertAssert(); + } + } + } + GC.KeepAlive(initialWndProc); + } + + + ~HwndWrapper() + { + Dispose(/*disposing = */ false, + /*isHwndBeingDestroyed = */ false); + } + + public virtual void Dispose() + { + // VerifyAccess(); + + Dispose(/*disposing = */ true, + /*isHwndBeingDestroyed = */ false); + GC.SuppressFinalize(this); + } + + // internal Dispose(bool, bool) + /// + /// TreatAsSafe: we demand when constructed, disposing considered safe + /// Critical: Elevates by calling an UnsafeNativeMethod + /// + [SecurityTreatAsSafe, SecurityCritical] + private void Dispose(bool disposing, bool isHwndBeingDestroyed) + { + if (_isDisposed) + { + // protect against re-entrancy: Calling DestroyWindow here will send + // a WM_NCDESTROY -- WndProc may catch this and call Dispose again. + return; + } + + if(disposing) + { + // diposing == false means we're being called from the finalizer + // and can't follow any reference types that may themselves be + // finalizable - thus don't call the Disposed callback. + + // Notify listeners that we are being disposed. + if(Disposed != null) + { + Disposed(this, EventArgs.Empty); + } + } + + // We are now considered disposed. + _isDisposed = true; + + + if (isHwndBeingDestroyed) + { + // The window is in the process of being destroyed. We can't call UnregisterClass yet + // so we'll ask the Dispatcher to do it later when the window is gone. + Dispatcher.BeginInvoke(DispatcherPriority.Normal, (DispatcherOperationCallback)UnregisterClass, _classAtom); + } + else if (_handle != null && _handle.Value != IntPtr.Zero) + { + // The window isn't in the process of being destroyed and it hasn't been destroyed yet + // (we know this since we're listening for WM_NCDESTROY). Since we're being disposed + // we destroy it now. + + if(Thread.CurrentThread.ManagedThreadId == _ownerThreadID.Value) + { + // We are the owner thread, we can safely destroy the window and unregister + // the class + DestroyWindow(new DestroyWindowArgs(_handle, _classAtom)); + } + else + { + // Post a DispatcherOperation to ask the owner thread to destroy the window for us. + Dispatcher.BeginInvoke( + DispatcherPriority.Normal, + (DispatcherOperationCallback)DestroyWindow, + new DestroyWindowArgs(_handle, _classAtom)); + } + } + + + _classAtom = 0; + _handle = null; + } + + /// + /// Critical: Returns the handle of the window + /// + public IntPtr Handle { + [SecurityCritical] + get + { + // This could be called from other threads, so snap the member. + SecurityCriticalDataClass handle = _handle; + + if (handle != null) + { + return handle.Value; + } + else + { + return IntPtr.Zero; + } + } + } + + public event EventHandler Disposed; + + /// + /// Critical: Used to add hooks to the system which can be used to listen to window messages + /// + [SecurityCritical] + public void AddHook(HwndWrapperHook hook) + { + //VerifyAccess(); + if(_hooks == null) + { + _hooks = new SecurityCriticalDataClass(new WeakReferenceList()); + } + + _hooks.Value.Insert(0, hook); + } + + /// + /// Critical: Used to add hooks to the system which can be used to listen to window messages + /// + [SecurityCritical] + internal void AddHookLast(HwndWrapperHook hook) + { + if(_hooks == null) + { + _hooks = new SecurityCriticalDataClass(new WeakReferenceList()); + } + _hooks.Value.Add(hook); + } + + /// + /// Critical: This code acceses critical value hooks + /// + [SecurityCritical] + public void RemoveHook(HwndWrapperHook hook) + { + //VerifyAccess(); + if (_hooks != null) + { + _hooks.Value.Remove(hook); + } + } + + /// + /// Critical: Calls the hooks and can be used to send spurious input to the system + /// + [SecurityCritical] + private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + // The default result for messages we handle is 0. + IntPtr result = IntPtr.Zero; + WindowMessage message = (WindowMessage)msg; + + // Call all of the hooks + if(_hooks != null) + { + foreach(HwndWrapperHook hook in _hooks.Value) + { + result = hook(hwnd, msg, wParam, lParam, ref handled); + + CheckForCreateWindowFailure(result, handled); + + if(handled) + { + break; + } + } + } + + if (message == WindowMessage.WM_NCDESTROY) + { + Dispose(/*disposing = */ true, + /*isHwndBeingDestroyed = */ true); + GC.SuppressFinalize(this); + + // We want the default window proc to process this message as + // well, so we mark it as unhandled. + handled = false; + } + else if (message == s_msgGCMemory) + { + // This is a special message we respond to by forcing a GC Collect. This + // is used by test apps and such. + IntPtr lHeap = (IntPtr)GC.GetTotalMemory((wParam == new IntPtr(1) )? true : false); + result = lHeap; + handled = true; + } + + CheckForCreateWindowFailure(result, true); + + // return our result + return result; + } + + private void CheckForCreateWindowFailure( IntPtr result, bool handled ) + { + if( ! _isInCreateWindow ) + return; + + if( IntPtr.Zero != result ) + { + System.Diagnostics.Debug.WriteLine("Non-zero WndProc result=" + result); + if( handled ) + { + if( System.Diagnostics.Debugger.IsAttached ) + System.Diagnostics.Debugger.Break(); + else + throw new InvalidOperationException(); + } + } + } + + + /// + /// Destroys the window with the given handle and class atom and unregisters its window class + /// + /// A DestrowWindowParams instance + /// + /// Critical: Destroys a Window and calls a critical method + /// Partial Trust scenarios can execute this method. It takes an object so that it + /// can be called by a DispatcherOperationCallback and avoid a DynamicInvoke, which + /// requires ReflectionPermission. + /// + [SecurityCritical] + internal static object DestroyWindow(object args) + { + SecurityCriticalDataClass handle = ((DestroyWindowArgs)args).Handle; + ushort classAtom = ((DestroyWindowArgs)args).ClassAtom; + + Invariant.Assert(handle != null && handle.Value != IntPtr.Zero, + "Attempting to destroy an invalid hwnd"); + + UnsafeNativeMethods.DestroyWindow(new HandleRef(null, handle.Value)); + + UnregisterClass((object)classAtom); + + return null; + } + + /// + /// Unregisters the window class represented by classAtom + /// + /// A ushort representing the class atom + /// + /// Critical: Unregisters the window class and calls a critical method + /// Partial Trust scenarios can execute this method. It takes an object so that it + /// can be called by a DispatcherOperationCallback and avoid a DynamicInvoke, which + /// requires ReflectionPermission. + /// + [SecurityCritical] + internal static object UnregisterClass(object arg) + { + ushort classAtom = (ushort)arg; + + if (classAtom != 0) + { + IntPtr hInstance = UnsafeNativeMethods.GetModuleHandle(null); + UnsafeNativeMethods.UnregisterClass( + new IntPtr(classAtom), //* this function is defined as taking a type lpClassName - but this can be an atom. 2 Low Bytes are the atom*/ + hInstance); + } + + return null; + } + + // This is used only so that DestroyWindow can take a single object parameter + // in order for it to be called by a DispatcherOperationCallback + internal class DestroyWindowArgs + { + public DestroyWindowArgs(SecurityCriticalDataClass handle, ushort classAtom) + { + _handle = handle; + _classAtom = classAtom; + } + + public SecurityCriticalDataClass Handle + { + get + { + return _handle; + } + } + + public ushort ClassAtom + { + get + { + return _classAtom; + } + } + + private SecurityCriticalDataClass _handle; + private ushort _classAtom; + } + + + private SecurityCriticalDataClass _handle; + private UInt16 _classAtom; + private SecurityCriticalDataClass _hooks; + private SecurityCriticalDataForSet _ownerThreadID; + + /// + /// Critical: Provides access to Win32 message loop which is considerd an elevation of privilage + /// + [SecurityCritical] + private SecurityCriticalData _wndProc; + private bool _isDisposed; + + private bool _isInCreateWindow = false; // debugging variable (temporary) + + // Message to cause a dispose. We need this to ensure we destroy the window on the right thread. + /// + /// Critical: This is initialized under an elevation + /// + [SecurityCritical] + private static WindowMessage s_msgGCMemory; + } // class RawWindow +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndWrapperHook.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndWrapperHook.cs new file mode 100644 index 00000000000..6c2f790fef7 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/HwndWrapperHook.cs @@ -0,0 +1,26 @@ +using System; +using System.Security; +using System.Security.Permissions; + +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif DRT + using MS.Internal.Drt; +#else +#error Attempt to use FriendAccessAllowedAttribute from an unknown assembly. +using MS.Internal.YourAssemblyName; +#endif + +namespace MS.Win32 +{ + /// + /// Critical: This can be used to inject hooks into avalon + /// + [SecurityCritical] + [FriendAccessAllowed] + internal delegate IntPtr HwndWrapperHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled); +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/LoadLibraryHelper.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/LoadLibraryHelper.cs new file mode 100644 index 00000000000..1a1bf397068 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/LoadLibraryHelper.cs @@ -0,0 +1,117 @@ +//--------------------------------------------------------------------------- +// +// +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// +// +// Description: Helper class for calling LoadLibrary using SEARCH_SYSTEM32 when possible +// +//--------------------------------------------------------------------------- + +namespace MS.Win32 +{ + using System; + using System.Security; + using System.Security.Permissions; + using System.Runtime.InteropServices; + + + + internal static class LoadLibraryHelper + { + /// + /// Identifies whether functionality introduced by KB2533623 is + /// available. + /// + /// + /// KB2533623 introduced kernel32!AddDllDirectoryName. We look for this + /// method to determine the result of this method. + /// + /// + /// Critical: Calls into P/Invoke methods + /// Safe: Returns a safe boolean to the caller + /// + [SecuritySafeCritical] + private static bool IsKnowledgeBase2533623OrGreater() + { + const string AddDllDirectoryName = nameof(AddDllDirectoryName); + + bool isKnowledgeBase2533623OrGreater = false; + + // We don't throw if one of these Win32 calls fail - we play it safe + // and return false + var hModule = IntPtr.Zero; + if (UnsafeNativeMethods.GetModuleHandleEx( + UnsafeNativeMethods.GetModuleHandleFlags.None, + ExternDll.Kernel32, + out hModule) && + hModule != IntPtr.Zero) + { + try + { + isKnowledgeBase2533623OrGreater = + UnsafeNativeMethods.GetProcAddressNoThrow(new HandleRef(null, hModule), AddDllDirectoryName) != IntPtr.Zero; + } + finally + { + UnsafeNativeMethods.FreeLibrary(hModule); + } + } + + return isKnowledgeBase2533623OrGreater; + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// The following require KB2532445 to be installed. The + /// presence of KB2533623 can be tested by looking for AddDllDirectories export in kernel32.dll + /// + /// + /// + /// + /// + /// + /// + /// The folowing flags require KB2532445. We do not provide any support for safely using this flag, and + /// leave it up to a future change to this implementation to add the right checks. + /// + /// + /// Critical: + /// Calls into Critical P/Invoke methods + /// Returns native module handle + /// + [SecurityCritical] + internal static IntPtr SecureLoadLibraryEx(string lpFileName, IntPtr hFile, UnsafeNativeMethods.LoadLibraryFlags dwFlags) + { + if (!IsKnowledgeBase2533623OrGreater()) + { + // Edit out the unsupported flags + if ((dwFlags & + UnsafeNativeMethods.LoadLibraryFlags.LOAD_LIBRARY_SEARCH_APPLICATION_DIR & + UnsafeNativeMethods.LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS & + UnsafeNativeMethods.LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR & + UnsafeNativeMethods.LoadLibraryFlags.LOAD_LIBRARY_SEARCH_SYSTEM32 & + UnsafeNativeMethods.LoadLibraryFlags.LOAD_LIBRARY_SEARCH_USER_DIRS) != UnsafeNativeMethods.LoadLibraryFlags.None) + { + dwFlags &= ~( + UnsafeNativeMethods.LoadLibraryFlags.LOAD_LIBRARY_SEARCH_APPLICATION_DIR | + UnsafeNativeMethods.LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | + UnsafeNativeMethods.LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | + UnsafeNativeMethods.LoadLibraryFlags.LOAD_LIBRARY_SEARCH_SYSTEM32 | + UnsafeNativeMethods.LoadLibraryFlags.LOAD_LIBRARY_SEARCH_USER_DIRS); + } + } + +#pragma warning disable CS0618 // Type or member is obsolete + return UnsafeNativeMethods.LoadLibraryEx(lpFileName, hFile, dwFlags); +#pragma warning restore CS0618 // Type or member is obsolete + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/ManagedWndProcTracker.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/ManagedWndProcTracker.cs new file mode 100644 index 00000000000..50c22460060 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/ManagedWndProcTracker.cs @@ -0,0 +1,315 @@ +//#define LOGGING + +using System; +using System.Collections; +using System.Threading; + +using System.Runtime.InteropServices; +using MS.Internal; +using MS.Internal.Interop; +using System.Security; +using System.Security.Permissions; + +// The SecurityHelper class differs between assemblies and could not actually be +// shared, so it is duplicated across namespaces to prevent name collision. +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif DRT + using MS.Internal.Drt; +#else +#error Attempt to use a class (duplicated across multiple namespaces) from an unknown assembly. +#endif + +namespace MS.Win32 +{ + internal static class ManagedWndProcTracker + { + /// + /// Critical: This code calls into Link demanded methods to attach handlers + /// TreatAsSafe: This code does not take any parameter or return state. + /// It simply attaches private call back. + /// + [SecurityCritical,SecurityTreatAsSafe] + static ManagedWndProcTracker() + { + // Listen for ProcessExit so we can detach ourselves when the CLR shuts down + // and avoid unmanaged code from calling back in to managed code during shutdown. + ManagedWndProcTrackerShutDownListener listener = new ManagedWndProcTrackerShutDownListener(); + } + + /// + /// Critical: Uses critical member _hwndList + /// + [SecurityCritical] + internal static void TrackHwndSubclass(HwndSubclass subclass, IntPtr hwnd) + { + lock (_hwndList) + { + // We use HwndSubclass as the key and the hwnd ptr as the value. + // This supports the case where two (or more) HwndSubclasses + // get attached to the same Hwnd. At AppDomain shutdown, we may + // end up sending the Detach message to the Hwnd more than once, + // but that won't cause any harm. + _hwndList[subclass] = hwnd; + } + +#if LOGGING + LogStartHWND(hwnd, "Core HwndWrapper..ctor"); +#endif + } + + /// + /// Critical: Uses critical member _hwndList + /// + [SecurityCritical] + internal static void UnhookHwndSubclass(HwndSubclass subclass) + { + // if exiting the AppDomain, ignore this call. This avoids changing + // the list during the loop in OnAppDomainProcessExit + if (_exiting) + return; + + lock (_hwndList) + { + _hwndList.Remove(subclass); + } + } + + /// + /// Critical performs an elevation to call HookUpDefWindowProc. + /// TreatAsSafe - net effect of this is to remove our already registered WndProc's on domain shutdown. + /// safe - as you had to elevate to add these already. Removing them is considered safe. + /// + [SecurityCritical, SecurityTreatAsSafe] + private static void OnAppDomainProcessExit() + { + // AppDomain is exiting -- if anyone tries to call back into managed code + // after this point, bad things will happen. We must remove all unmanaged + // code references to our WndProc delegates. USER will explode if we set the + // WndProc to null, so the next most reasonable thing we can do is hook up + // the DefaultWindowProc. + //DbgUserBreakPoint(); + + _exiting = true; + + lock (_hwndList) + { + new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); // BlessedAssert: + try + { + foreach (DictionaryEntry entry in _hwndList) + { + IntPtr hwnd = (IntPtr)entry.Value; + + int windowStyle = UnsafeNativeMethods.GetWindowLong(new HandleRef(null,hwnd), NativeMethods.GWL_STYLE); + if((windowStyle & NativeMethods.WS_CHILD) != 0) + { + // Tell all the HwndSubclass WndProcs for WS_CHILD windows + // to detach themselves. This is particularly important when + // the parent hwnd belongs to a separate AppDomain in a + // cross AppDomain hosting scenario. In this scenario it is + // possible that the host has subclassed the WS_CHILD window + // and hence it is important to notify the host before we set the + // WndProc to DefWndProc. Also note that we do not want to make a + // blocking SendMessage call to all the subclassed Hwnds in the + // AppDomain because this can lead to slow shutdown speed. + // Eg. Consider a MessageOnlyHwnd created and subclassed on a + // worker thread which is no longer responsive. The SendMessage + // call in this case will block. To avoid this we limit the conversation + // only to WS_CHILD windows. We understand that this solution is + // not foolproof but it is the best outside of re-designing the cleanup + // of Hwnd subclasses. + + UnsafeNativeMethods.SendMessage(hwnd, HwndSubclass.DetachMessage, + IntPtr.Zero /* wildcard */, + (IntPtr) 2 /* force and forward */); + } + + // the last WndProc on the chain might be managed as well + // (see HwndSubclass.SubclassWndProc for explanation). + // Just in case, restore the DefaultWindowProc. + HookUpDefWindowProc(hwnd); + } + } + finally + { + CodeAccessPermission.RevertAssert(); + } + + } + } + + /// + /// TreatAsSafe: Demands for unmanaged code + /// Critical: Elevates by calling an unverifieds UnsafeNativeMethod call + /// + [SecurityTreatAsSafe, SecurityCritical] + private static void HookUpDefWindowProc(IntPtr hwnd) + { + + SecurityHelper.DemandUnmanagedCode(); + +#if LOGGING + LogFinishHWND(hwnd, "Core HookUpDWP"); +#endif + + IntPtr result = IntPtr.Zero ; + + // We've already cleaned up, return immediately. + if (hwnd == IntPtr.Zero) + { + return; + } + + IntPtr defWindowProc = GetDefWindowProcAddress(hwnd); + + if (defWindowProc != IntPtr.Zero) + { + try + { + result = UnsafeNativeMethods.SetWindowLong(new HandleRef(null,hwnd), NativeMethods.GWL_WNDPROC, defWindowProc); + + } + catch(System.ComponentModel.Win32Exception e) + { + // We failed to change the window proc. Now what? + + if (e.NativeErrorCode != 1400) // ERROR_INVALID_WINDOW_HANDLE + { + // For debugging purposes, throw an exception so we can debug + // this and know if it's possible to call SetWindowLong on + // the wrong thread. + throw; + } + } + if (result != IntPtr.Zero ) + { + UnsafeNativeMethods.PostMessage(new HandleRef(null,hwnd), WindowMessage.WM_CLOSE, IntPtr.Zero, IntPtr.Zero); + } + } + } + + // Get the DWP for the given HWND -- returns DefWindowProcA or DefWindowProcW + // depending on IsWindowUnicode(hwnd). + private static IntPtr GetDefWindowProcAddress(IntPtr hwnd) + { + // We need to swap back in the DefWindowProc, but which one we use depends on + // what the Unicode-ness of the window. + if (SafeNativeMethods.IsWindowUnicode(new HandleRef(null,hwnd))) + { + if (_cachedDefWindowProcW == IntPtr.Zero) + { + _cachedDefWindowProcW = GetUser32ProcAddress("DefWindowProcW"); + } + + return _cachedDefWindowProcW; + } + else + { + if (_cachedDefWindowProcA == IntPtr.Zero) + { + _cachedDefWindowProcA = GetUser32ProcAddress("DefWindowProcA") ; + } + + return _cachedDefWindowProcA; + } + } + + /// + /// SecurityCritical: elevates via a call to unsafe native methods + /// SecurityTreatAsSafe: Demands unmgd code permission via SecurityHelper + /// + [SecurityCritical, SecurityTreatAsSafe] + private static IntPtr GetUser32ProcAddress(string export) + { + + SecurityHelper.DemandUnmanagedCode(); + IntPtr hModule = UnsafeNativeMethods.GetModuleHandle(ExternDll.User32); + + + if (hModule != IntPtr.Zero) + { + return UnsafeNativeMethods.GetProcAddress(new HandleRef(null, hModule), export); + + } + return IntPtr.Zero; + } + + private sealed class ManagedWndProcTrackerShutDownListener : ShutDownListener + { + /// + /// Critical: accesses AppDomain.DomainUnload event + /// TreatAsSafe: This code does not take any parameter or return state. + /// It simply attaches private callbacks. + /// + [SecurityCritical,SecurityTreatAsSafe] + public ManagedWndProcTrackerShutDownListener() + : base(null, ShutDownEvents.AppDomain) + { + } + + internal override void OnShutDown(object target, object sender, EventArgs e) + { + ManagedWndProcTracker.OnAppDomainProcessExit(); + } + } + +#if LOGGING + [DllImport("ntdll.dll")] + private static extern void DbgUserBreakPoint(); + + [DllImport("ntdll.dll")] + private static extern void DbgPrint(string msg); + + internal static void LogStartHWND(IntPtr hwnd, string fromWhere) + { + string msg = String.Format("BEGIN: {0:X} -- Setting DWP, process = {1} ({2}) {3}", + hwnd, + System.Diagnostics.Process.GetCurrentProcess().ProcessName, + fromWhere, + System.Environment.NewLine); + + Log(msg); + } + + internal static void LogFinishHWND(IntPtr hwnd, string fromWhere) + { + string msg = String.Format("END: {0:X} -- Setting DWP, process = {1} ({2}) {3}", + hwnd, + System.Diagnostics.Process.GetCurrentProcess().ProcessName, + fromWhere, + System.Environment.NewLine); + + Log(msg); + } + + private static void Log(string msg) + { + //DbgUserBreakPoint(); + /* + byte[] msgBytes = System.Text.Encoding.ASCII.GetBytes(msg); + System.IO.FileStream fs = System.IO.File.Open("c:\\dwplog.txt", System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite); + + fs.Write(msgBytes, 0, msgBytes.Length); + fs.Flush(); + fs.Close(); + */ + } + +#endif + + private static IntPtr _cachedDefWindowProcA = IntPtr.Zero; + private static IntPtr _cachedDefWindowProcW = IntPtr.Zero; + + /// + /// Critical - used as input to unsafe calls + /// + [SecurityCritical] + private static Hashtable _hwndList = new Hashtable(10); + private static bool _exiting = false; + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/MessageOnlyHwndWrapper.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/MessageOnlyHwndWrapper.cs new file mode 100644 index 00000000000..9ee83f471df --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/MessageOnlyHwndWrapper.cs @@ -0,0 +1,21 @@ + +using System; +using System.Threading; +using System.Security ; +using System.Runtime.InteropServices; + +namespace MS.Win32 +{ + // Specialized version of HwndWrapper for message-only windows. + + internal class MessageOnlyHwndWrapper : HwndWrapper + { + /// + /// Critical: This code calls into base class which is critical + /// + [SecurityCritical] + public MessageOnlyHwndWrapper() : base(0, 0, 0, 0, 0, 0, 0, "", NativeMethods.HWND_MESSAGE, null) + { + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsCLR.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsCLR.cs new file mode 100644 index 00000000000..ae41ce16c6d --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsCLR.cs @@ -0,0 +1,7309 @@ +#pragma warning disable 649 // Disable CS0649: "field is never assigned to" + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +namespace MS.Win32 { + using Accessibility; + using System.Runtime.InteropServices; + using System; + using System.Security.Permissions; + using System.Collections; + using System.Diagnostics; + using System.IO; + using System.Text; + using MS.Internal; +#if !DRT && !UIAUTOMATIONTYPES + using MS.Internal.Interop; +#endif + using Microsoft.Win32; + using System.Security; + // The SecurityHelper class differs between assemblies and could not actually be + // shared, so it is duplicated across namespaces to prevent name collision. +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif UIAUTOMATIONTYPES + using MS.Internal.UIAutomationTypes; +#elif DRT + using MS.Internal.Drt; +#else +#error Attempt to use a class (duplicated across multiple namespaces) from an unknown assembly. +#endif + + internal partial class NativeMethods { + #if !FRAMEWORK_NATIVEMETHODS + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class XFORM { + public float eM11; + public float eM12; + public float eM21; + public float eM22; + public float eDx; + public float eDy; + + public XFORM() + { + this.eM11 = this.eM22 = 1; // identity matrix. + } + + public XFORM( float em11, float em12, float em21, float em22, float edx, float edy ) + { + this.eM11 = em11; + this.eM12 = em12; + this.eM21 = em21; + this.eM22 = em22; + this.eDx = edx; + this.eDy = edy; + } + + public XFORM( float[] elements ) + { + this.eM11 = elements[0]; + this.eM12 = elements[1]; + this.eM21 = elements[2]; + this.eM22 = elements[3]; + this.eDx = elements[4]; + this.eDy = elements[5]; + } + + public override string ToString() + { + return String.Format(System.Globalization.CultureInfo.CurrentCulture,"[{0}, {1}, {2}, {3}, {4}, {5}]", this.eM11, this.eM12, this.eM21, this.eM22, this.eDx, this.eDy ); + } + + public override bool Equals( object obj ) + { + XFORM xform = obj as XFORM; + + if( xform == null ) + { + return false; + } + + return this.eM11 == xform.eM11 && + this.eM12 == xform.eM12 && + this.eM21 == xform.eM21 && + this.eM22 == xform.eM22 && + this.eDx == xform.eDx && + this.eDy == xform.eDy; + } + + public override int GetHashCode() + { + return this.ToString().GetHashCode(); + } + + } +#endif + + public static IntPtr InvalidIntPtr = (IntPtr)(-1); + public static IntPtr LPSTR_TEXTCALLBACK = (IntPtr)(-1); + public static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero); + + public const int ERROR = 0; + + public const int BITMAPINFO_MAX_COLORSIZE = 256; +#if never + public const int BI_BITFIELDS = 3; + + public enum RegionFlags { + ERROR = 0, + NULLREGION = 1, + SIMPLEREGION = 2, + COMPLEXREGION = 3, + } + + public const int + /* FONT WEIGHT (BOLD) VALUES */ + FW_DONTCARE = 0, + FW_NORMAL = 400, + FW_BOLD = 700, + // some others... + + /* FONT CHARACTER SET */ + ANSI_CHARSET = 0, + DEFAULT_CHARSET = 1, + // plus others .... + + /* Font OutPrecision */ + OUT_DEFAULT_PRECIS = 0, + OUT_TT_PRECIS = 4, + OUT_TT_ONLY_PRECIS = 7, + + /* polygon fill mode */ + ALTERNATE = 1, + WINDING = 2, + + // text align + TA_DEFAULT = 0, + + // brush + BS_SOLID = 0, + HOLLOW_BRUSH = 5, + + // Binary raster operations. + R2_BLACK = 1, /* 0 */ + R2_NOTMERGEPEN = 2, /* DPon */ + R2_MASKNOTPEN = 3, /* DPna */ + R2_NOTCOPYPEN = 4, /* PN */ + R2_MASKPENNOT = 5, /* PDna */ + R2_NOT = 6, /* Dn */ + R2_XORPEN = 7, /* DPx */ + R2_NOTMASKPEN = 8, /* DPan */ + R2_MASKPEN = 9, /* DPa */ + R2_NOTXORPEN = 10, /* DPxn */ + R2_NOP = 11, /* D */ + R2_MERGENOTPEN = 12, /* DPno */ + R2_COPYPEN = 13, /* P */ + R2_MERGEPENNOT = 14, /* PDno */ + R2_MERGEPEN = 15, /* DPo */ + R2_WHITE = 16 /* 1 */; + + + public const int + /* SetGraphicsMode(hdc, iMode ) */ + GM_COMPATIBLE = 1, + GM_ADVANCED = 2, + MWT_IDENTITY = 1; + +#endif + public const int +// PAGE_READONLY = 0x02, + PAGE_READWRITE = 0x04, +// PAGE_WRITECOPY = 0x08, +// FILE_MAP_COPY = 0x0001, +// FILE_MAP_WRITE = 0x0002, + FILE_MAP_READ = 0x0004; + + public const int APPCOMMAND_BROWSER_BACKWARD = 1; + public const int APPCOMMAND_BROWSER_FORWARD = 2; + public const int APPCOMMAND_BROWSER_REFRESH = 3; + public const int APPCOMMAND_BROWSER_STOP = 4; + public const int APPCOMMAND_BROWSER_SEARCH = 5; + public const int APPCOMMAND_BROWSER_FAVORITES = 6; + public const int APPCOMMAND_BROWSER_HOME = 7; + public const int APPCOMMAND_VOLUME_MUTE = 8; + public const int APPCOMMAND_VOLUME_DOWN = 9; + public const int APPCOMMAND_VOLUME_UP = 10; + public const int APPCOMMAND_MEDIA_NEXTTRACK = 11; + public const int APPCOMMAND_MEDIA_PREVIOUSTRACK = 12; + public const int APPCOMMAND_MEDIA_STOP = 13; + public const int APPCOMMAND_MEDIA_PLAY_PAUSE = 14; + public const int APPCOMMAND_LAUNCH_MAIL = 15; + public const int APPCOMMAND_LAUNCH_MEDIA_SELECT = 16; + public const int APPCOMMAND_LAUNCH_APP1 = 17; + public const int APPCOMMAND_LAUNCH_APP2 = 18; + public const int APPCOMMAND_BASS_DOWN = 19; + public const int APPCOMMAND_BASS_BOOST = 20; + public const int APPCOMMAND_BASS_UP = 21; + public const int APPCOMMAND_TREBLE_DOWN = 22; + public const int APPCOMMAND_TREBLE_UP = 23; + public const int APPCOMMAND_MICROPHONE_VOLUME_MUTE = 24; + public const int APPCOMMAND_MICROPHONE_VOLUME_DOWN = 25; + public const int APPCOMMAND_MICROPHONE_VOLUME_UP = 26; + public const int APPCOMMAND_HELP = 27; + public const int APPCOMMAND_FIND = 28; + public const int APPCOMMAND_NEW = 29; + public const int APPCOMMAND_OPEN = 30; + public const int APPCOMMAND_CLOSE = 31; + public const int APPCOMMAND_SAVE = 32; + public const int APPCOMMAND_PRINT = 33; + public const int APPCOMMAND_UNDO = 34; + public const int APPCOMMAND_REDO = 35; + public const int APPCOMMAND_COPY = 36; + public const int APPCOMMAND_CUT = 37; + public const int APPCOMMAND_PASTE = 38; + public const int APPCOMMAND_REPLY_TO_MAIL = 39; + public const int APPCOMMAND_FORWARD_MAIL = 40; + public const int APPCOMMAND_SEND_MAIL = 41; + public const int APPCOMMAND_SPELL_CHECK = 42; + public const int APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE = 43; + public const int APPCOMMAND_MIC_ON_OFF_TOGGLE = 44; + public const int APPCOMMAND_CORRECTION_LIST = 45; + public const int APPCOMMAND_MEDIA_PLAY = 46; + public const int APPCOMMAND_MEDIA_PAUSE = 47; + public const int APPCOMMAND_MEDIA_RECORD = 48; + public const int APPCOMMAND_MEDIA_FAST_FORWARD = 49; + public const int APPCOMMAND_MEDIA_REWIND = 50; + public const int APPCOMMAND_MEDIA_CHANNEL_UP = 51; + public const int APPCOMMAND_MEDIA_CHANNEL_DOWN = 52; + public const int FAPPCOMMAND_MOUSE = 0x8000; + public const int FAPPCOMMAND_KEY = 0; + public const int FAPPCOMMAND_OEM = 0x1000; + public const int FAPPCOMMAND_MASK = 0xF000; + +#if never + + public const int SHGFI_ICON = 0x000000100 , // get icon + SHGFI_DISPLAYNAME = 0x000000200, // get display name + SHGFI_TYPENAME = 0x000000400, // get type name + SHGFI_ATTRIBUTES = 0x000000800, // get attributes + SHGFI_ICONLOCATION = 0x000001000, // get icon location + SHGFI_EXETYPE = 0x000002000, // return exe type + SHGFI_SYSICONINDEX = 0x000004000, // get system icon index + SHGFI_LINKOVERLAY = 0x000008000, // put a link overlay on icon + SHGFI_SELECTED = 0x000010000, // show icon in selected state + SHGFI_ATTR_SPECIFIED = 0x000020000, // get only specified attributes + SHGFI_LARGEICON = 0x000000000, // get large icon + SHGFI_SMALLICON = 0x000000001, // get small icon + SHGFI_OPENICON = 0x000000002, // get open icon + SHGFI_SHELLICONSIZE = 0x000000004, // get shell size icon + SHGFI_PIDL = 0x000000008, // pszPath is a pidl + SHGFI_USEFILEATTRIBUTES = 0x000000010, // use passed dwFileAttribute + SHGFI_ADDOVERLAYS = 0x000000020, // apply the appropriate overlays + SHGFI_OVERLAYINDEX = 0x000000040; // Get the index of the overlay + + public const int DM_DISPLAYORIENTATION = 0x00000080; + + public const int AUTOSUGGEST = 0x10000000, + AUTOSUGGEST_OFF = 0x20000000, + AUTOAPPEND = 0x40000000, + AUTOAPPEND_OFF = (unchecked((int)0x80000000)); + + public const int ARW_BOTTOMLEFT = 0x0000, + ARW_BOTTOMRIGHT = 0x0001, + ARW_TOPLEFT = 0x0002, + ARW_TOPRIGHT = 0x0003, + ARW_LEFT = 0x0000, + ARW_RIGHT = 0x0000, + ARW_UP = 0x0004, + ARW_DOWN = 0x0004, + ARW_HIDE = 0x0008, + ACM_OPENA = (0x0400+100), + ACM_OPENW = (0x0400+103), + ADVF_NODATA = 1, + ADVF_ONLYONCE = 4, + ADVF_PRIMEFIRST = 2; + // Note: ADVF_ONLYONCE and ADVF_PRIMEFIRST values now conform with objidl.dll but are backwards from + // Platform SDK documentation as of 07/21/2003. + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/oen_a2z_8jxi.asp. + // See VSWhidbey bug#96162. + + public const int BCM_GETIDEALSIZE = 0x1601; +#endif + public const int BI_RGB = 0; +#if never + BS_PATTERN = 3, +#endif + public const int BITSPIXEL = 12; +#if never + BDR_RAISEDOUTER = 0x0001, + BDR_SUNKENOUTER = 0x0002, + BDR_RAISEDINNER = 0x0004, + BDR_SUNKENINNER = 0x0008, + BDR_RAISED = 0x0005, + BDR_SUNKEN = 0x000a, + BF_LEFT = 0x0001, + BF_TOP = 0x0002, + BF_RIGHT = 0x0004, + BF_BOTTOM = 0x0008, + BF_ADJUST = 0x2000, + BF_FLAT = 0x4000, + BF_MIDDLE = 0x0800, + BFFM_INITIALIZED = 1, + BFFM_SELCHANGED = 2, + BFFM_SETSELECTION = 0x400+103, + BFFM_ENABLEOK = 0x400+101, + BS_PUSHBUTTON = 0x00000000, + BS_DEFPUSHBUTTON = 0x00000001, + BS_MULTILINE = 0x00002000, + BS_PUSHLIKE = 0x00001000, + BS_OWNERDRAW = 0x0000000B, + BS_RADIOBUTTON = 0x00000004, + BS_3STATE = 0x00000005, + BS_GROUPBOX = 0x00000007, + BS_LEFT = 0x00000100, + BS_RIGHT = 0x00000200, + BS_CENTER = 0x00000300, + BS_TOP = 0x00000400, + BS_BOTTOM = 0x00000800, + BS_VCENTER = 0x00000C00, + BS_RIGHTBUTTON = 0x00000020, + BN_CLICKED = 0, + BM_SETCHECK = 0x00F1, + BM_SETSTATE = 0x00F3, + BM_CLICK = 0x00F5; + + public const int CDERR_DIALOGFAILURE = 0xFFFF, + CDERR_STRUCTSIZE = 0x0001, + CDERR_INITIALIZATION = 0x0002, + CDERR_NOTEMPLATE = 0x0003, + CDERR_NOHINSTANCE = 0x0004, + CDERR_LOADSTRFAILURE = 0x0005, + CDERR_FINDRESFAILURE = 0x0006, + CDERR_LOADRESFAILURE = 0x0007, + CDERR_LOCKRESFAILURE = 0x0008, + CDERR_MEMALLOCFAILURE = 0x0009, + CDERR_MEMLOCKFAILURE = 0x000A, + CDERR_NOHOOK = 0x000B, + CDERR_REGISTERMSGFAIL = 0x000C, + CFERR_NOFONTS = 0x2001, + CFERR_MAXLESSTHANMIN = 0x2002, + CC_RGBINIT = 0x00000001, + CC_FULLOPEN = 0x00000002, + CC_PREVENTFULLOPEN = 0x00000004, + CC_SHOWHELP = 0x00000008, + CC_ENABLEHOOK = 0x00000010, + CC_SOLIDCOLOR = 0x00000080, + CC_ANYCOLOR = 0x00000100, + CF_SCREENFONTS = 0x00000001, + CF_SHOWHELP = 0x00000004, + CF_ENABLEHOOK = 0x00000008, + CF_INITTOLOGFONTSTRUCT = 0x00000040, + CF_EFFECTS = 0x00000100, + CF_APPLY = 0x00000200, + CF_SCRIPTSONLY = 0x00000400, + CF_NOVECTORFONTS = 0x00000800, + CF_NOSIMULATIONS = 0x00001000, + CF_LIMITSIZE = 0x00002000, + CF_FIXEDPITCHONLY = 0x00004000, + CF_FORCEFONTEXIST = 0x00010000, + CF_TTONLY = 0x00040000, + CF_SELECTSCRIPT = 0x00400000, + CF_NOVERTFONTS = 0x01000000, + CP_WINANSI = 1004; +#endif + public const int + cmb4 = 0x0473, + CS_DBLCLKS = 0x0008, + CS_DROPSHADOW = 0x00020000, + CS_SAVEBITS = 0x0800, + CF_TEXT = 1, + CF_BITMAP = 2, + CF_METAFILEPICT = 3, + CF_SYLK = 4, + CF_DIF = 5, + CF_TIFF = 6, + CF_OEMTEXT = 7, + CF_DIB = 8, + CF_PALETTE = 9, + CF_PENDATA = 10, + CF_RIFF = 11, + CF_WAVE = 12, + CF_UNICODETEXT = 13, + CF_ENHMETAFILE = 14, + CF_HDROP = 15, + CF_LOCALE = 16, + CLSCTX_INPROC_SERVER = 0x1, + CLSCTX_LOCAL_SERVER = 0x4, + CW_USEDEFAULT = (unchecked((int)0x80000000)), + CWP_SKIPINVISIBLE = 0x0001, + COLOR_WINDOW = 5, + CB_ERR = (-1), + CBN_SELCHANGE = 1, + CBN_DBLCLK = 2, + CBN_EDITCHANGE = 5, + CBN_EDITUPDATE = 6, + CBN_DROPDOWN = 7, + CBN_CLOSEUP = 8, + CBN_SELENDOK = 9, + CBS_SIMPLE = 0x0001, + CBS_DROPDOWN = 0x0002, + CBS_DROPDOWNLIST = 0x0003, + CBS_OWNERDRAWFIXED = 0x0010, + CBS_OWNERDRAWVARIABLE = 0x0020, + CBS_AUTOHSCROLL = 0x0040, + CBS_HASSTRINGS = 0x0200, + CBS_NOINTEGRALHEIGHT = 0x0400, + CB_GETEDITSEL = 0x0140, + CB_LIMITTEXT = 0x0141, + CB_SETEDITSEL = 0x0142, + CB_ADDSTRING = 0x0143, + CB_DELETESTRING = 0x0144, + CB_GETCURSEL = 0x0147, + CB_GETLBTEXT = 0x0148, + CB_GETLBTEXTLEN = 0x0149, + CB_INSERTSTRING = 0x014A, + CB_RESETCONTENT = 0x014B, + CB_FINDSTRING = 0x014C, + CB_SETCURSEL = 0x014E, + CB_SHOWDROPDOWN = 0x014F, + CB_GETITEMDATA = 0x0150, + CB_SETITEMHEIGHT = 0x0153, + CB_GETITEMHEIGHT = 0x0154, + CB_GETDROPPEDSTATE = 0x0157, + CB_FINDSTRINGEXACT = 0x0158, + CB_SETDROPPEDWIDTH = 0x0160, + CDRF_DODEFAULT = 0x00000000, + CDRF_NEWFONT = 0x00000002, + CDRF_SKIPDEFAULT = 0x00000004, + CDRF_NOTIFYPOSTPAINT = 0x00000010, + CDRF_NOTIFYITEMDRAW = 0x00000020, + CDRF_NOTIFYSUBITEMDRAW = CDRF_NOTIFYITEMDRAW, + CDDS_PREPAINT = 0x00000001, + CDDS_POSTPAINT = 0x00000002, + CDDS_ITEM = 0x00010000, + CDDS_SUBITEM = 0x00020000, + CDDS_ITEMPREPAINT = (0x00010000|0x00000001), + CDDS_ITEMPOSTPAINT = (0x00010000|0x00000002), + CDIS_SELECTED = 0x0001, + CDIS_GRAYED = 0x0002, + CDIS_DISABLED = 0x0004, + CDIS_CHECKED = 0x0008, + CDIS_FOCUS = 0x0010, + CDIS_DEFAULT = 0x0020, + CDIS_HOT = 0x0040, + CDIS_MARKED = 0x0080, + CDIS_INDETERMINATE = 0x0100, + CDIS_SHOWKEYBOARDCUES = 0x0200, + CLR_NONE = unchecked((int)0xFFFFFFFF), + CLR_DEFAULT = unchecked((int)0xFF000000), + CCM_SETVERSION = (0x2000+0x7), + CCM_GETVERSION = (0x2000+0x8), + CCS_NORESIZE = 0x00000004, + CCS_NOPARENTALIGN = 0x00000008, + CCS_NODIVIDER = 0x00000040, + CBEM_INSERTITEMA = (0x0400+1), + CBEM_GETITEMA = (0x0400+4), + CBEM_SETITEMA = (0x0400+5), + CBEM_INSERTITEMW = (0x0400+11), + CBEM_SETITEMW = (0x0400+12), + CBEM_GETITEMW = (0x0400+13), + CBEN_ENDEDITA = ((0-800)-5), + CBEN_ENDEDITW = ((0-800)-6), + CONNECT_E_NOCONNECTION = unchecked((int)0x80040200), + CONNECT_E_CANNOTCONNECT = unchecked((int)0x80040202), + CTRLINFO_EATS_RETURN = 1, + CTRLINFO_EATS_ESCAPE = 2, + CSIDL_DESKTOP = 0x0000, // + CSIDL_INTERNET = 0x0001, // Internet Explorer (icon on desktop) + CSIDL_PROGRAMS = 0x0002, // Start Menu\Programs + CSIDL_PERSONAL = 0x0005, // My Documents + CSIDL_FAVORITES = 0x0006, // \Favorites + CSIDL_STARTUP = 0x0007, // Start Menu\Programs\Startup + CSIDL_RECENT = 0x0008, // \Recent + CSIDL_SENDTO = 0x0009, // \SendTo + CSIDL_STARTMENU = 0x000b, // \Start Menu + CSIDL_DESKTOPDIRECTORY = 0x0010, // \Desktop + CSIDL_TEMPLATES = 0x0015, + CSIDL_APPDATA = 0x001a, // \Application Data + CSIDL_LOCAL_APPDATA = 0x001c, // \Local Settings\Applicaiton Data (non roaming) + CSIDL_INTERNET_CACHE = 0x0020, + CSIDL_COOKIES = 0x0021, + CSIDL_HISTORY = 0x0022, + CSIDL_COMMON_APPDATA = 0x0023, // All Users\Application Data + CSIDL_SYSTEM = 0x0025, // GetSystemDirectory() + CSIDL_PROGRAM_FILES = 0x0026, // C:\Program Files + CSIDL_PROGRAM_FILES_COMMON = 0x002b; // C:\Program Files\Common + + public const int DUPLICATE = 0x06, + DISPID_VALUE = 0, + DISPID_UNKNOWN = (-1), + DISPID_PROPERTYPUT = (-3), + DISPATCH_METHOD = 0x1, + DISPATCH_PROPERTYGET = 0x2, + DISPATCH_PROPERTYPUT = 0x4, + DISPATCH_PROPERTYPUTREF = 0x8, + DV_E_DVASPECT = unchecked((int)0x8004006B), + DEFAULT_GUI_FONT = 17, + DIB_RGB_COLORS = 0, + DRAGDROP_E_NOTREGISTERED = unchecked((int)0x80040100), + DRAGDROP_E_ALREADYREGISTERED = unchecked((int)0x80040101), + DUPLICATE_SAME_ACCESS = 0x00000002, + DFC_CAPTION = 1, + DFC_MENU = 2, + DFC_SCROLL = 3, + DFC_BUTTON = 4, + DFCS_CAPTIONCLOSE = 0x0000, + DFCS_CAPTIONMIN = 0x0001, + DFCS_CAPTIONMAX = 0x0002, + DFCS_CAPTIONRESTORE = 0x0003, + DFCS_CAPTIONHELP = 0x0004, + DFCS_MENUARROW = 0x0000, + DFCS_MENUCHECK = 0x0001, + DFCS_MENUBULLET = 0x0002, + DFCS_SCROLLUP = 0x0000, + DFCS_SCROLLDOWN = 0x0001, + DFCS_SCROLLLEFT = 0x0002, + DFCS_SCROLLRIGHT = 0x0003, + DFCS_SCROLLCOMBOBOX = 0x0005, + DFCS_BUTTONCHECK = 0x0000, + DFCS_BUTTONRADIO = 0x0004, + DFCS_BUTTON3STATE = 0x0008, + DFCS_BUTTONPUSH = 0x0010, + DFCS_INACTIVE = 0x0100, + DFCS_PUSHED = 0x0200, + DFCS_CHECKED = 0x0400, + DFCS_FLAT = 0x4000, + DT_LEFT = 0x00000000, + DT_RIGHT = 0x00000002, + DT_VCENTER = 0x00000004, + DT_SINGLELINE = 0x00000020, + DT_NOCLIP = 0x00000100, + DT_CALCRECT = 0x00000400, + DT_NOPREFIX = 0x00000800, + DT_EDITCONTROL = 0x00002000, + DT_EXPANDTABS = 0x00000040, + DT_END_ELLIPSIS = 0x00008000, + DT_RTLREADING = 0x00020000, + DT_WORDBREAK = 0x00000010, + DCX_WINDOW = 0x00000001, + DCX_CACHE = 0x00000002, + DCX_LOCKWINDOWUPDATE = 0x00000400, + DI_NORMAL = 0x0003, + DLGC_WANTARROWS = 0x0001, + DLGC_WANTTAB = 0x0002, + DLGC_WANTALLKEYS = 0x0004, + DLGC_WANTCHARS = 0x0080, + DTM_GETSYSTEMTIME = (0x1000+1), + DTM_SETSYSTEMTIME = (0x1000+2), + DTM_SETRANGE = (0x1000+4), + DTM_SETFORMATA = (0x1000+5), + DTM_SETFORMATW = (0x1000+50), + DTM_SETMCCOLOR = (0x1000+6), + DTM_SETMCFONT = (0x1000+9), + DTS_UPDOWN = 0x0001, + DTS_SHOWNONE = 0x0002, + DTS_LONGDATEFORMAT = 0x0004, + DTS_TIMEFORMAT = 0x0009, + DTS_RIGHTALIGN = 0x0020, + DTN_DATETIMECHANGE = ((0-760)+1), + DTN_USERSTRINGA = ((0-760)+2), + DTN_USERSTRINGW = ((0-760)+15), + DTN_WMKEYDOWNA = ((0-760)+3), + DTN_WMKEYDOWNW = ((0-760)+16), + DTN_FORMATA = ((0-760)+4), + DTN_FORMATW = ((0-760)+17), + DTN_FORMATQUERYA = ((0-760)+5), + DTN_FORMATQUERYW = ((0-760)+18), + DTN_DROPDOWN = ((0-760)+6), + DTN_CLOSEUP = ((0-760)+7), + DVASPECT_CONTENT = 1, + DVASPECT_TRANSPARENT = 32, + DVASPECT_OPAQUE = 16; + + public const int E_NOTIMPL = unchecked((int)0x80004001), + E_OUTOFMEMORY = unchecked((int)0x8007000E), + E_INVALIDARG = unchecked((int)0x80070057), + E_NOINTERFACE = unchecked((int)0x80004002), + E_FAIL = unchecked((int)0x80004005), + E_ABORT = unchecked((int)0x80004004), + E_UNEXPECTED = unchecked((int)0x8000FFFF), + INET_E_DEFAULT_ACTION = unchecked((int)0x800C0011), + ETO_OPAQUE = 0x0002, + ETO_CLIPPED = 0x0004, + EMR_POLYTEXTOUTA = 96, + EMR_POLYTEXTOUTW = 97, + EDGE_RAISED = (0x0001|0x0004), + EDGE_SUNKEN = (0x0002|0x0008), + EDGE_ETCHED = (0x0002|0x0004), + EDGE_BUMP = (0x0001|0x0008), + ES_LEFT = 0x0000, + ES_CENTER = 0x0001, + ES_RIGHT = 0x0002, + ES_MULTILINE = 0x0004, + ES_UPPERCASE = 0x0008, + ES_LOWERCASE = 0x0010, + ES_AUTOVSCROLL = 0x0040, + ES_AUTOHSCROLL = 0x0080, + ES_NOHIDESEL = 0x0100, + ES_READONLY = 0x0800, + ES_PASSWORD = 0x0020, + EN_CHANGE = 0x0300, + EN_UPDATE = 0x0400, + EN_HSCROLL = 0x0601, + EN_VSCROLL = 0x0602, + EN_ALIGN_LTR_EC = 0x0700, + EN_ALIGN_RTL_EC = 0x0701, + EC_LEFTMARGIN = 0x0001, + EC_RIGHTMARGIN = 0x0002, + EM_GETSEL = 0x00B0, + EM_SETSEL = 0x00B1, + EM_SCROLL = 0x00B5, + EM_SCROLLCARET = 0x00B7, + EM_GETMODIFY = 0x00B8, + EM_SETMODIFY = 0x00B9, + EM_GETLINECOUNT = 0x00BA, + EM_REPLACESEL = 0x00C2, + EM_GETLINE = 0x00C4, + EM_LIMITTEXT = 0x00C5, + EM_CANUNDO = 0x00C6, + EM_UNDO = 0x00C7, + EM_SETPASSWORDCHAR = 0x00CC, + EM_GETPASSWORDCHAR = 0x00D2, + EM_EMPTYUNDOBUFFER = 0x00CD, + EM_SETREADONLY = 0x00CF, + EM_SETMARGINS = 0x00D3, + EM_POSFROMCHAR = 0x00D6, + EM_CHARFROMPOS = 0x00D7, + EM_LINEFROMCHAR = 0x00C9, + EM_LINEINDEX = 0x00BB; +#if never + + + public const int ERROR_CLASS_ALREADY_EXISTS = 1410; +#endif + + public const int FNERR_SUBCLASSFAILURE = 0x3001, + FNERR_INVALIDFILENAME = 0x3002, + FNERR_BUFFERTOOSMALL = 0x3003; + +#if never + public const int FRERR_BUFFERLENGTHZERO = 0x4001, + FADF_BSTR = (0x100), + FADF_UNKNOWN = (0x200), + FADF_DISPATCH = (0x400), + FADF_VARIANT = (unchecked((int)0x800)), + FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000, + FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200, + FVIRTKEY = 0x01, + FSHIFT = 0x04, + FALT = 0x10; +#endif + + public const int GMEM_MOVEABLE = 0x0002, + GMEM_ZEROINIT = 0x0040, + GMEM_DDESHARE = 0x2000, + GCL_WNDPROC = (-24), + GWL_WNDPROC = (-4), + GWL_HWNDPARENT = (-8), + GWL_STYLE = (-16), + GWL_EXSTYLE = (-20), + GWL_ID = (-12), + GW_HWNDFIRST = 0, + GW_HWNDLAST = 1, + GW_HWNDNEXT = 2, + GW_HWNDPREV = 3, + GW_OWNER = 4, + GW_CHILD = 5, + GMR_VISIBLE = 0, + GMR_DAYSTATE = 1, + GDI_ERROR = (unchecked((int)0xFFFFFFFF)), + GDTR_MIN = 0x0001, + GDTR_MAX = 0x0002, + GDT_VALID = 0, + GDT_NONE = 1, + GA_PARENT = 1, + GA_ROOT = 2; + + // ImmGetCompostionString index. + public const int + GCS_COMPREADSTR = 0x0001, + GCS_COMPREADATTR = 0x0002, + GCS_COMPREADCLAUSE = 0x0004, + GCS_COMPSTR = 0x0008, + GCS_COMPATTR = 0x0010, + GCS_COMPCLAUSE = 0x0020, + GCS_CURSORPOS = 0x0080, + GCS_DELTASTART = 0x0100, + GCS_RESULTREADSTR = 0x0200, + GCS_RESULTREADCLAUSE = 0x0400, + GCS_RESULTSTR = 0x0800, + GCS_RESULTCLAUSE = 0x1000, + + // attribute for COMPOSITIONSTRING Structure + ATTR_INPUT = 0x00, + ATTR_TARGET_CONVERTED = 0x01, + ATTR_CONVERTED = 0x02, + ATTR_TARGET_NOTCONVERTED = 0x03, + ATTR_INPUT_ERROR = 0x04, + ATTR_FIXEDCONVERTED = 0x05, + + // dwAction for ImmNotifyIME + NI_COMPOSITIONSTR = 0x0015, + + // wParam of report message WM_IME_NOTIFY + IMN_CLOSESTATUSWINDOW = 0x0001, + IMN_OPENSTATUSWINDOW = 0x0002, + IMN_CHANGECANDIDATE = 0x0003, + IMN_CLOSECANDIDATE = 0x0004, + IMN_OPENCANDIDATE = 0x0005, + IMN_SETCONVERSIONMODE = 0x0006, + IMN_SETSENTENCEMODE = 0x0007, + IMN_SETOPENSTATUS = 0x0008, + IMN_SETCANDIDATEPOS = 0x0009, + IMN_SETCOMPOSITIONFONT = 0x000A, + IMN_SETCOMPOSITIONWINDOW = 0x000B, + IMN_SETSTATUSWINDOWPOS = 0x000C, + IMN_GUIDELINE = 0x000D, + IMN_PRIVATE = 0x000E, + + // dwIndex for ImmNotifyIME/NI_COMPOSITIONSTR + CPS_COMPLETE = 0x01, + CPS_CANCEL = 0x04, + + // dwStyle for CANDIDATEFORM + CFS_DEFAULT = 0x0000, + CFS_RECT = 0x0001, + CFS_POINT = 0x0002, + CFS_FORCE_POSITION = 0x0020, + CFS_CANDIDATEPOS = 0x0040, + CFS_EXCLUDE = 0x0080, + + // bit field for conversion mode + IME_CMODE_ALPHANUMERIC = 0x0000, + IME_CMODE_NATIVE = 0x0001, + IME_CMODE_CHINESE = 0x0001, // IME_CMODE_NATIVE, + IME_CMODE_HANGEUL = 0x0001, // IME_CMODE_NATIVE, + IME_CMODE_HANGUL = 0x0001, // IME_CMODE_NATIVE, + IME_CMODE_JAPANESE = 0x0001, // IME_CMODE_NATIVE, + IME_CMODE_KATAKANA = 0x0002, // only effect under IME_CMODE_NATIVE + IME_CMODE_LANGUAGE = 0x0003, + IME_CMODE_FULLSHAPE = 0x0008, + IME_CMODE_ROMAN = 0x0010, + IME_CMODE_CHARCODE = 0x0020, + IME_CMODE_HANJACONVERT = 0x0040, + IME_CMODE_SOFTKBD = 0x0080, + IME_CMODE_NOCONVERSION = 0x0100, + IME_CMODE_EUDC = 0x0200, + IME_CMODE_SYMBOL = 0x0400, + IME_CMODE_FIXED = 0x0800, + IME_CMODE_RESERVED = unchecked((int)0xF0000000), + + // bit field for sentence mode + IME_SMODE_NONE = 0x0000, + IME_SMODE_PLAURALCLAUSE = 0x0001, + IME_SMODE_SINGLECONVERT = 0x0002, + IME_SMODE_AUTOMATIC = 0x0004, + IME_SMODE_PHRASEPREDICT = 0x0008, + IME_SMODE_CONVERSATION = 0x0010, + IME_SMODE_RESERVED = 0x0000F000, + + IME_CAND_UNKNOWN = 0x0000, + IME_CAND_READ = 0x0001, + IME_CAND_CODE = 0x0002, + IME_CAND_MEANING = 0x0003, + IME_CAND_RADICAL = 0x0004, + IME_CAND_STROKE = 0x0005, + + IMR_COMPOSITIONWINDOW = 0x0001, + IMR_CANDIDATEWINDOW = 0x0002, + IMR_COMPOSITIONFONT = 0x0003, + IMR_RECONVERTSTRING = 0x0004, + IMR_CONFIRMRECONVERTSTRING = 0x0005, + IMR_QUERYCHARPOSITION = 0x0006, + IMR_DOCUMENTFEED = 0x0007, + + IME_CONFIG_GENERAL = 1, + IME_CONFIG_REGISTERWORD = 2, + IME_CONFIG_SELECTDICTIONARY = 3, + + IGP_GETIMEVERSION = (-4), + IGP_PROPERTY = 0x00000004, + IGP_CONVERSION = 0x00000008, + IGP_SENTENCE = 0x0000000c, + IGP_UI = 0x00000010, + IGP_SETCOMPSTR = 0x00000014, + IGP_SELECT = 0x00000018, + + IME_PROP_AT_CARET = 0x00010000, + IME_PROP_SPECIAL_UI = 0x00020000, + IME_PROP_CANDLIST_START_FROM_1 = 0x00040000, + IME_PROP_UNICODE = 0x00080000, + IME_PROP_COMPLETE_ON_UNSELECT = 0x00100000; + + // CANDIDATEFORM structures + [StructLayout(LayoutKind.Sequential)] + public struct CANDIDATEFORM + { + public int dwIndex; + public int dwStyle; + public POINT ptCurrentPos; + public RECT rcArea; + } + + // COMPOSITIONFORM structures + [StructLayout(LayoutKind.Sequential)] + public struct COMPOSITIONFORM + { + public int dwStyle; + public POINT ptCurrentPos; + public RECT rcArea; + } + + // RECONVERTSTRING structures + [StructLayout(LayoutKind.Sequential)] + public struct RECONVERTSTRING + { + public int dwSize; + public int dwVersion; + public int dwStrLen; + public int dwStrOffset; + public int dwCompStrLen; + public int dwCompStrOffset; + public int dwTargetStrLen; + public int dwTargetStrOffset; + } + + // REGISTERWORD structures + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public struct REGISTERWORD + { + public string lpReading; + public string lpWord; + } + + public const int + HC_ACTION = 0, + HC_GETNEXT = 1, + HC_SKIP = 2, + HTNOWHERE = 0, + HTCLIENT = 1, + HTBOTTOM = 15, + HTTRANSPARENT = (-1), + HTBOTTOMLEFT = 16, + HTBOTTOMRIGHT = 17, + HELPINFO_WINDOW = 0x0001, + HCF_HIGHCONTRASTON = 0x00000001, + HDI_ORDER = 0x0080, + HDI_WIDTH = 0x0001, + HDM_GETITEMCOUNT = (0x1200+0), + HDM_INSERTITEMA = (0x1200+1), + HDM_INSERTITEMW = (0x1200+10), + HDM_GETITEMA = (0x1200+3), + HDM_GETITEMW = (0x1200+11), + HDM_SETITEMA = (0x1200+4), + HDM_SETITEMW = (0x1200+12), + HDN_ITEMCHANGINGA = ((0-300)-0), + HDN_ITEMCHANGINGW = ((0-300)-20), + HDN_ITEMCHANGEDA = ((0-300)-1), + HDN_ITEMCHANGEDW = ((0-300)-21), + HDN_ITEMCLICKA = ((0-300)-2), + HDN_ITEMCLICKW = ((0-300)-22), + HDN_ITEMDBLCLICKA = ((0-300)-3), + HDN_ITEMDBLCLICKW = ((0-300)-23), + HDN_DIVIDERDBLCLICKA = ((0-300)-5), + HDN_DIVIDERDBLCLICKW = ((0-300)-25), + HDN_BEGINTDRAG = ((0-300)-10), + HDN_BEGINTRACKA = ((0-300)-6), + HDN_BEGINTRACKW = ((0-300)-26), + HDN_ENDDRAG = ((0-300)-11), + HDN_ENDTRACKA = ((0-300)-7), + HDN_ENDTRACKW = ((0-300)-27), + HDN_TRACKA = ((0-300)-8), + HDN_TRACKW = ((0-300)-28), + HDN_GETDISPINFOA = ((0-300)-9), + HDN_GETDISPINFOW = ((0-300)-29); + // HOVER_DEFAULT = Do not use this value ever! It crashes entire servers. +#if never + + public const int HDS_FULLDRAG = 0x0080; + + // Corresponds to bitmaps in MENUITEMINFO + public const int HBMMENU_CALLBACK = -1, + HBMMENU_SYSTEM = 1, + HBMMENU_MBAR_RESTORE = 2, + HBMMENU_MBAR_MINIMIZE = 3, + HBMMENU_MBAR_CLOSE = 5, + HBMMENU_MBAR_CLOSE_D = 6, + HBMMENU_MBAR_MINIMIZE_D = 7, + HBMMENU_POPUP_CLOSE = 8, + HBMMENU_POPUP_RESTORE = 9, + HBMMENU_POPUP_MAXIMIZE = 10, + HBMMENU_POPUP_MINIMIZE = 11; +#endif + + public static HandleRef HWND_TOP = new HandleRef(null, (IntPtr)0); + public static HandleRef HWND_BOTTOM = new HandleRef(null, (IntPtr)1); + public static HandleRef HWND_TOPMOST = new HandleRef(null, new IntPtr(-1)); + public static HandleRef HWND_NOTOPMOST = new HandleRef(null, new IntPtr(-2)); + // NOTE: NativeMethodsOther.cs defines the following + //public static IntPtr HWND_MESSAGE = new IntPtr(-3); + + + public const int INPLACE_E_NOTOOLSPACE = unchecked((int)0x800401A1), + ICON_SMALL = 0, + ICON_BIG = 1, + IDC_ARROW = 32512, + IDC_IBEAM = 32513, + IDC_WAIT = 32514, + IDC_CROSS = 32515, + IDC_SIZEALL = 32646, + IDC_SIZENWSE = 32642, + IDC_SIZENESW = 32643, + IDC_SIZEWE = 32644, + IDC_SIZENS = 32645, + IDC_UPARROW = 32516, + IDC_NO = 32648, + IDC_APPSTARTING = 32650, + IDC_HELP = 32651, + IMAGE_ICON = 1, + IMAGE_CURSOR = 2, + ICC_LISTVIEW_CLASSES = 0x00000001, + ICC_TREEVIEW_CLASSES = 0x00000002, + ICC_BAR_CLASSES = 0x00000004, + ICC_TAB_CLASSES = 0x00000008, + ICC_PROGRESS_CLASS = 0x00000020, + ICC_DATE_CLASSES = 0x00000100, + ILC_MASK = 0x0001, + ILC_COLOR = 0x0000, + ILC_COLOR4 = 0x0004, + ILC_COLOR8 = 0x0008, + ILC_COLOR16 = 0x0010, + ILC_COLOR24 = 0x0018, + ILC_COLOR32 = 0x0020, + ILC_MIRROR = 0x00002000, + ILD_NORMAL = 0x0000, + ILD_TRANSPARENT = 0x0001, + ILD_MASK = 0x0010, + ILD_ROP = 0x0040, + + // ImageList + // + ILP_NORMAL = 0, + ILP_DOWNLEVEL = 1, + ILS_NORMAL = 0x0, + ILS_GLOW = 0x1, + ILS_SHADOW = 0x2, + ILS_SATURATE = 0x4, + ILS_ALPHA = 0x8; + + public const int CSC_NAVIGATEFORWARD = 0x00000001, + CSC_NAVIGATEBACK = 0x00000002; + +#if never + + public const int IDM_PRINT = 27, + IDM_PAGESETUP = 2004, + IDM_PRINTPREVIEW = 2003, + IDM_PROPERTIES = 28, + IDM_SAVEAS = 71; + + + + public const int STG_E_INVALIDFUNCTION = unchecked((int)0x80030001); + public const int STG_E_FILENOTFOUND = unchecked((int)0x80030002); + public const int STG_E_PATHNOTFOUND = unchecked((int)0x80030003); + public const int STG_E_TOOMANYOPENFILES = unchecked((int)0x80030004); + public const int STG_E_ACCESSDENIED = unchecked((int)0x80030005); + public const int STG_E_INVALIDHANDLE = unchecked((int)0x80030006); + public const int STG_E_INSUFFICIENTMEMORY = unchecked((int)0x80030008); + public const int STG_E_INVALIDPOINTER = unchecked((int)0x80030009); + public const int STG_E_NOMOREFILES = unchecked((int)0x80030012); + public const int STG_E_DISKISWRITEPROTECTED = unchecked((int)0x80030013); + public const int STG_E_SEEKERROR = unchecked((int)0x80030019); + public const int STG_E_WRITEFAULT = unchecked((int)0x8003001D); + public const int STG_E_READFAULT = unchecked((int)0x8003001E); + public const int STG_E_SHAREVIOLATION = unchecked((int)0x80030020); + public const int STG_E_LOCKVIOLATION = unchecked((int)0x80030021); +#endif + public const int STG_E_CANTSAVE = unchecked((int)0x80030103); +#if never + + public const int KEYEVENTF_KEYUP = 0x0002; +#endif + + public const int LOGPIXELSX = 88, + LOGPIXELSY = 90, + LB_ERR = (-1), + LB_ERRSPACE = (-2), + LBN_SELCHANGE = 1, + LBN_DBLCLK = 2, + LB_ADDSTRING = 0x0180, + LB_INSERTSTRING = 0x0181, + LB_DELETESTRING = 0x0182, + LB_RESETCONTENT = 0x0184, + LB_SETSEL = 0x0185, + LB_SETCURSEL = 0x0186, + LB_GETSEL = 0x0187, + LB_GETCARETINDEX = 0x019F, + LB_GETCURSEL = 0x0188, + LB_GETTEXT = 0x0189, + LB_GETTEXTLEN = 0x018A, + LB_GETTOPINDEX = 0x018E, + LB_FINDSTRING = 0x018F, + LB_GETSELCOUNT = 0x0190, + LB_GETSELITEMS = 0x0191, + LB_SETTABSTOPS = 0x0192, + LB_SETHORIZONTALEXTENT = 0x0194, + LB_SETCOLUMNWIDTH = 0x0195, + LB_SETTOPINDEX = 0x0197, + LB_GETITEMRECT = 0x0198, + LB_SETITEMHEIGHT = 0x01A0, + LB_GETITEMHEIGHT = 0x01A1, + LB_FINDSTRINGEXACT = 0x01A2, + LB_ITEMFROMPOINT = 0x01A9, + LB_SETLOCALE = 0x01A5; +#if never + + public const int LBS_NOTIFY = 0x0001, + LBS_MULTIPLESEL = 0x0008, + LBS_OWNERDRAWFIXED = 0x0010, + LBS_OWNERDRAWVARIABLE = 0x0020, + LBS_HASSTRINGS = 0x0040, + LBS_USETABSTOPS = 0x0080, + LBS_NOINTEGRALHEIGHT = 0x0100, + LBS_MULTICOLUMN = 0x0200, + LBS_WANTKEYBOARDINPUT = 0x0400, + LBS_EXTENDEDSEL = 0x0800, + LBS_DISABLENOSCROLL = 0x1000, + LBS_NOSEL = 0x4000, + LOCK_WRITE = 0x1, + LOCK_EXCLUSIVE = 0x2, + LOCK_ONLYONCE = 0x4, + LV_VIEW_TILE = 0x0004, + LVBKIF_SOURCE_NONE = 0x0000, + LVBKIF_SOURCE_URL = 0x0002, + LVBKIF_STYLE_NORMAL = 0x0000, + LVBKIF_STYLE_TILE = 0x0010, + LVS_ICON = 0x0000, + LVS_REPORT = 0x0001, + LVS_SMALLICON = 0x0002, + LVS_LIST = 0x0003, + LVS_SINGLESEL = 0x0004, + LVS_SHOWSELALWAYS = 0x0008, + LVS_SORTASCENDING = 0x0010, + LVS_SORTDESCENDING = 0x0020, + LVS_SHAREIMAGELISTS = 0x0040, + LVS_NOLABELWRAP = 0x0080, + LVS_AUTOARRANGE = 0x0100, + LVS_EDITLABELS = 0x0200, + LVS_NOSCROLL = 0x2000, + LVS_ALIGNTOP = 0x0000, + LVS_ALIGNLEFT = 0x0800, + LVS_NOCOLUMNHEADER = 0x4000, + LVS_NOSORTHEADER = unchecked((int)0x8000), + LVS_OWNERDATA = 0x1000, + LVSCW_AUTOSIZE = -1, + LVSCW_AUTOSIZE_USEHEADER = -2, + LVM_REDRAWITEMS = (0x1000+21), + LVM_SCROLL=(0x1000+20), + LVM_SETBKCOLOR = (0x1000+1), + LVM_SETBKIMAGEA = (0x1000+68), + LVM_SETBKIMAGEW = (0x1000+138), + LVM_SETCALLBACKMASK = (0x1000+11), + LVM_GETCALLBACKMASK = (0x1000+10), + LVM_SETINFOTIP = (0x1000+173), + LVSIL_NORMAL = 0, + LVSIL_SMALL = 1, + LVSIL_STATE = 2, + LVM_SETIMAGELIST = (0x1000+3), + LVM_SETTOOLTIPS = (0x1000+74), + LVIF_TEXT = 0x0001, + LVIF_IMAGE = 0x0002, + LVIF_INDENT = 0x0010, + LVIF_PARAM = 0x0004, + LVIF_STATE = 0x0008, + LVIF_GROUPID = 0x0100, + LVIF_COLUMNS = 0x0200, + LVIS_FOCUSED = 0x0001, + LVIS_SELECTED = 0x0002, + LVIS_CUT = 0x0004, + LVIS_DROPHILITED = 0x0008, + LVIS_OVERLAYMASK = 0x0F00, + LVIS_STATEIMAGEMASK = 0xF000, + LVM_GETITEMA = (0x1000+5), + LVM_GETITEMW = (0x1000+75), + LVM_SETITEMA = (0x1000+6), + LVM_SETITEMW = (0x1000+76), + LVM_SETITEMPOSITION32 = (0x01000 + 49), + LVM_INSERTITEMA = (0x1000+7), + LVM_INSERTITEMW = (0x1000+77), + LVM_DELETEITEM = (0x1000+8), + LVM_DELETECOLUMN = (0x1000+28), + LVM_DELETEALLITEMS = (0x1000+9), + LVM_UPDATE = (0x1000+42), + LVNI_FOCUSED = 0x0001, + LVNI_SELECTED = 0x0002, + LVM_GETNEXTITEM = (0x1000+12), + LVFI_PARAM = 0x0001, + LVFI_NEARESTXY = 0x0040, + LVFI_PARTIAL = 0x0008, + LVFI_STRING = 0x0002, + LVM_FINDITEMA = (0x1000+13), + LVM_FINDITEMW = (0x1000+83), + LVIR_BOUNDS = 0, + LVIR_ICON = 1, + LVIR_LABEL = 2, + LVIR_SELECTBOUNDS = 3, + LVM_GETITEMPOSITION = (0x1000+16), + LVM_GETITEMRECT = (0x1000+14), + LVM_GETSUBITEMRECT = (0x1000+56), + LVM_GETSTRINGWIDTHA = (0x1000+17), + LVM_GETSTRINGWIDTHW = (0x1000+87), + LVHT_NOWHERE = 0x0001, + LVHT_ONITEMICON = 0x0002, + LVHT_ONITEMLABEL = 0x0004, + LVHT_ABOVE = 0x0008, + LVHT_BELOW = 0x0010, + LVHT_RIGHT = 0x0020, + LVHT_LEFT = 0x0040, + LVHT_ONITEM = (0x0002|0x0004|0x0008), + LVHT_ONITEMSTATEICON = 0x0008, + LVM_SUBITEMHITTEST = (0x1000 + 57), + LVM_HITTEST = (0x1000+18), + LVM_ENSUREVISIBLE = (0x1000+19), + LVA_DEFAULT = 0x0000, + LVA_ALIGNLEFT = 0x0001, + LVA_ALIGNTOP = 0x0002, + LVA_SNAPTOGRID = 0x0005, + LVM_ARRANGE = (0x1000+22), + LVM_EDITLABELA = (0x1000+23), + LVM_EDITLABELW = (0x1000+118), + LVCDI_ITEM = 0x0000, + LVCF_FMT = 0x0001, + LVCF_WIDTH = 0x0002, + LVCF_TEXT = 0x0004, + LVCF_SUBITEM = 0x0008, + LVCF_IMAGE = 0x0010, + LVCF_ORDER = 0x0020, + LVCFMT_IMAGE = 0x0800, + LVGA_HEADER_LEFT = 0x00000001, + LVGA_HEADER_CENTER = 0x00000002, + LVGA_HEADER_RIGHT = 0x00000004, + LVGA_FOOTER_LEFT = 0x00000008, + LVGA_FOOTER_CENTER = 0x00000010, + LVGA_FOOTER_RIGHT = 0x00000020, + LVGF_NONE = 0x00000000, + LVGF_HEADER = 0x00000001, + LVGF_FOOTER = 0x00000002, + LVGF_STATE = 0x00000004, + LVGF_ALIGN = 0x00000008, + LVGF_GROUPID = 0x00000010, + LVGS_NORMAL = 0x00000000, + LVGS_COLLAPSED = 0x00000001, + LVGS_HIDDEN = 0x00000002, + LVIM_AFTER = 0x00000001, + LVTVIF_FIXEDSIZE = 0x00000003, + LVTVIM_TILESIZE = 0x00000001, + LVTVIM_COLUMNS = 0x00000002, + LVM_ENABLEGROUPVIEW = (0x1000 + 157), + LVM_MOVEITEMTOGROUP = (0x1000 + 154), + LVM_GETCOLUMNA = (0x1000+25), + LVM_GETCOLUMNW = (0x1000+95), + LVM_SETCOLUMNA = (0x1000+26), + LVM_SETCOLUMNW = (0x1000+96), + LVM_INSERTCOLUMNA = (0x1000+27), + LVM_INSERTCOLUMNW = (0x1000+97), + LVM_INSERTGROUP = (0x1000 + 145), + LVM_REMOVEGROUP = (0x1000 + 150), + LVM_INSERTMARKHITTEST = (0x1000 + 168), + LVM_REMOVEALLGROUPS = (0x1000 + 160), + LVM_GETCOLUMNWIDTH = (0x1000+29), + LVM_SETCOLUMNWIDTH = (0x1000+30), + LVM_SETINSERTMARK = (0x1000 + 166), + LVM_GETHEADER = (0x1000+31), + LVM_SETTEXTCOLOR = (0x1000+36), + LVM_SETTEXTBKCOLOR = (0x1000+38), + LVM_GETTOPINDEX = (0x1000+39), + LVM_SETITEMPOSITION = (0x1000+15), + LVM_SETITEMSTATE = (0x1000+43), + LVM_GETITEMSTATE = (0x1000+44), + LVM_GETITEMTEXTA = (0x1000+45), + LVM_GETITEMTEXTW = (0x1000+115), + LVM_GETHOTITEM = (0x1000+61), + LVM_SETITEMTEXTA = (0x1000+46), + LVM_SETITEMTEXTW = (0x1000+116), + LVM_SETITEMCOUNT = (0x1000+47), + LVM_SORTITEMS = (0x1000+48), + LVM_GETSELECTEDCOUNT = (0x1000+50), + LVM_GETISEARCHSTRINGA = (0x1000+52), + LVM_GETISEARCHSTRINGW = (0x1000+117), + LVM_SETEXTENDEDLISTVIEWSTYLE = (0x1000+54), + LVM_SETVIEW = (0x1000 + 142), + LVM_GETGROUPINFO = (0x1000 + 149), + LVM_SETGROUPINFO = (0x1000 + 147), + LVM_HASGROUP = (0x1000 + 161), + LVM_SETTILEVIEWINFO = (0x1000 + 162), + LVM_GETTILEVIEWINFO = (0x1000 + 163), + LVM_GETINSERTMARK = (0x1000 + 167), + LVM_GETINSERTMARKRECT = (0x1000 + 169), + LVM_SETINSERTMARKCOLOR = (0x1000 + 170), + LVM_GETINSERTMARKCOLOR = (0x1000 + 171), + LVM_ISGROUPVIEWENABLED = (0x1000 + 175), + LVS_EX_GRIDLINES = 0x00000001, + LVS_EX_CHECKBOXES = 0x00000004, + LVS_EX_TRACKSELECT = 0x00000008, + LVS_EX_HEADERDRAGDROP = 0x00000010, + LVS_EX_FULLROWSELECT = 0x00000020, + LVS_EX_ONECLICKACTIVATE = 0x00000040, + LVS_EX_TWOCLICKACTIVATE = 0x00000080, + LVS_EX_INFOTIP = 0x00000400, + LVS_EX_UNDERLINEHOT = 0x00000800, + LVS_EX_DOUBLEBUFFER = 0x00010000, + LVN_ITEMCHANGING = ((0-100)-0), + LVN_ITEMCHANGED = ((0-100)-1), + LVN_BEGINLABELEDITA = ((0-100)-5), + LVN_BEGINLABELEDITW = ((0-100)-75), + LVN_ENDLABELEDITA = ((0-100)-6), + LVN_ENDLABELEDITW = ((0-100)-76), + LVN_COLUMNCLICK = ((0-100)-8), + LVN_BEGINDRAG = ((0-100)-9), + LVN_BEGINRDRAG = ((0-100)-11), + LVN_ODFINDITEMA = ((0-100)-52), + LVN_ODFINDITEMW = ((0-100)-79), + LVN_ITEMACTIVATE = ((0-100)-14), + LVN_GETDISPINFOA = ((0-100)-50), + LVN_GETDISPINFOW = ((0-100)-77), + LVN_ODCACHEHINT = ((0-100) - 13), + LVN_ODSTATECHANGED = ((0-100) - 15), + LVN_SETDISPINFOA = ((0-100)-51), + LVN_SETDISPINFOW = ((0-100)-78), + LVN_GETINFOTIPA = ((0-100)-57), + LVN_GETINFOTIPW = ((0-100)- 58), + LVN_KEYDOWN = ((0-100)-55), + + LWA_COLORKEY = 0x00000001, +#endif + public const int LWA_ALPHA = 0x00000002; +#if never + + public const int LANG_NEUTRAL = 0x00, + LOCALE_IFIRSTDAYOFWEEK = 0x0000100C; /* first day of week specifier */ + + public const int LOCALE_IMEASURE = 0x0000000D; // 0 = metric, 1 = US + + public static readonly int LOCALE_USER_DEFAULT = MAKELCID(LANG_USER_DEFAULT); + public static readonly int LANG_USER_DEFAULT = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); + + public static int MAKELANGID(int primary, int sub) { + return ((((ushort)(sub)) << 10) | (ushort)(primary)); + } + + /// + /// + /// Creates an LCID from a LangId + /// + public static int MAKELCID(int lgid) { + return MAKELCID(lgid, SORT_DEFAULT); + } + + /// + /// + /// Creates an LCID from a LangId + /// + public static int MAKELCID(int lgid, int sort) { + return ((0xFFFF & lgid) | (((0x000f) & sort) << 16)); + } + +#endif + + public const int MEMBERID_NIL = (-1), + MAX_PATH = 260, + MA_ACTIVATE = 0x0001, + MA_ACTIVATEANDEAT = 0x0002, + MA_NOACTIVATE = 0x0003, + MA_NOACTIVATEANDEAT = 0x0004, + MM_TEXT = 1, + MM_ANISOTROPIC = 8, + MK_LBUTTON = 0x0001, + MK_RBUTTON = 0x0002, + MK_SHIFT = 0x0004, + MK_CONTROL = 0x0008, + MK_MBUTTON = 0x0010, + MNC_EXECUTE = 2, + MNC_SELECT = 3, + MIIM_STATE = 0x00000001, + MIIM_ID = 0x00000002, + MIIM_SUBMENU = 0x00000004, + MIIM_TYPE = 0x00000010, + MIIM_DATA = 0x00000020, + MIIM_STRING = 0x00000040, + MIIM_BITMAP = 0x00000080, + MIIM_FTYPE = 0x00000100, + MB_OK = 0x00000000, + MF_BYCOMMAND = 0x00000000, + MF_BYPOSITION = 0x00000400, + MF_ENABLED = 0x00000000, + MF_GRAYED = 0x00000001, + MF_POPUP = 0x00000010, + MF_SYSMENU = 0x00002000, + MFS_DISABLED = 0x00000003, + MFT_MENUBREAK = 0x00000040, + MFT_SEPARATOR = 0x00000800, + MFT_RIGHTORDER = 0x00002000, + MFT_RIGHTJUSTIFY = 0x00004000, + MDIS_ALLCHILDSTYLES = 0x0001, + MDITILE_VERTICAL = 0x0000, + MDITILE_HORIZONTAL = 0x0001, + MDITILE_SKIPDISABLED = 0x0002, + MCM_SETMAXSELCOUNT = (0x1000+4), + MCM_SETSELRANGE = (0x1000+6), + MCM_GETMONTHRANGE = (0x1000+7), + MCM_GETMINREQRECT = (0x1000+9), + MCM_SETCOLOR = (0x1000+10), + MCM_SETTODAY = (0x1000+12), + MCM_GETTODAY = (0x1000+13), + MCM_HITTEST = (0x1000+14), + MCM_SETFIRSTDAYOFWEEK = (0x1000+15), + MCM_SETRANGE = (0x1000+18), + MCM_SETMONTHDELTA = (0x1000+20), + MCM_GETMAXTODAYWIDTH = (0x1000+21), + MCHT_TITLE = 0x00010000, + MCHT_CALENDAR = 0x00020000, + MCHT_TODAYLINK = 0x00030000, + MCHT_TITLEBK = (0x00010000), + MCHT_TITLEMONTH = (0x00010000|0x0001), + MCHT_TITLEYEAR = (0x00010000|0x0002), + MCHT_TITLEBTNNEXT = (0x00010000|0x01000000|0x0003), + MCHT_TITLEBTNPREV = (0x00010000|0x02000000|0x0003), + MCHT_CALENDARBK = (0x00020000), + MCHT_CALENDARDATE = (0x00020000|0x0001), + MCHT_CALENDARDATENEXT = ((0x00020000|0x0001)|0x01000000), + MCHT_CALENDARDATEPREV = ((0x00020000|0x0001)|0x02000000), + MCHT_CALENDARDAY = (0x00020000|0x0002), + MCHT_CALENDARWEEKNUM = (0x00020000|0x0003), + MCSC_TEXT = 1, + MCSC_TITLEBK = 2, + MCSC_TITLETEXT = 3, + MCSC_MONTHBK = 4, + MCSC_TRAILINGTEXT = 5, + MCN_SELCHANGE = ((0-750)+1), + MCN_GETDAYSTATE = ((0-750)+3), + MCN_SELECT = ((0-750)+4), + MCS_DAYSTATE = 0x0001, + MCS_MULTISELECT = 0x0002, + MCS_WEEKNUMBERS = 0x0004, + MCS_NOTODAYCIRCLE = 0x0008, + MCS_NOTODAY = 0x0010, + MSAA_MENU_SIG = (unchecked((int) 0xAA0DF00D)); + + //ActiveX related defines + public const int + OLECONTF_EMBEDDINGS = 0x1, + OLECONTF_LINKS = 0x2, + OLECONTF_OTHERS = 0x4, + OLECONTF_ONLYUSER = 0x8, + OLECONTF_ONLYIFRUNNING = 0x10, + OLEMISC_RECOMPOSEONRESIZE = 0x00000001, + OLEMISC_INSIDEOUT = 0x00000080, + OLEMISC_ACTIVATEWHENVISIBLE = 0x0000100, + OLEMISC_ACTSLIKEBUTTON = 0x00001000, + OLEMISC_SETCLIENTSITEFIRST = 0x00020000, + OLEIVERB_PRIMARY = 0, + OLEIVERB_SHOW = -1, + OLEIVERB_HIDE = -3, + OLEIVERB_UIACTIVATE = -4, + OLEIVERB_INPLACEACTIVATE = -5, + OLEIVERB_DISCARDUNDOSTATE= -6, + OLEIVERB_PROPERTIES = -7, + XFORMCOORDS_POSITION = 0x1, + XFORMCOORDS_SIZE = 0x2, + XFORMCOORDS_HIMETRICTOCONTAINER = 0x4, + XFORMCOORDS_CONTAINERTOHIMETRIC = 0x8; + +#if never + + public const int NIM_ADD = 0x00000000, + NIM_MODIFY = 0x00000001, + NIM_DELETE = 0x00000002, + NIF_MESSAGE = 0x00000001, + NIF_ICON = 0x00000002, + NIF_TIP = 0x00000004, + NFR_ANSI = 1, + NFR_UNICODE = 2, + NM_CLICK = ((0-0)-2), + NM_DBLCLK = ((0-0)-3), + NM_RCLICK = ((0-0)-5), + NM_RDBLCLK = ((0-0)-6), + NM_CUSTOMDRAW = ((0-0)-12), + NM_RELEASEDCAPTURE = ((0-0)-16), + NONANTIALIASED_QUALITY = 3; +#endif + + public const int OFN_READONLY = 0x00000001, + OFN_OVERWRITEPROMPT = 0x00000002, + OFN_HIDEREADONLY = 0x00000004, + OFN_NOCHANGEDIR = 0x00000008, + //OFN_SHOWHELP = 0x00000010, + OFN_ENABLEHOOK = 0x00000020, + OFN_NOVALIDATE = 0x00000100, + OFN_ALLOWMULTISELECT = 0x00000200, + OFN_PATHMUSTEXIST = 0x00000800, + OFN_FILEMUSTEXIST = 0x00001000, + OFN_CREATEPROMPT = 0x00002000, + OFN_EXPLORER = 0x00080000, + OFN_NODEREFERENCELINKS = 0x00100000, + OFN_ENABLESIZING = 0x00800000, + OFN_USESHELLITEM = 0x01000000; + +#if never + public const int OLEIVERB_PRIMARY = 0, + OLEIVERB_SHOW = -1, + OLEIVERB_HIDE = -3, + OLEIVERB_UIACTIVATE = -4, + OLEIVERB_INPLACEACTIVATE = -5, + OLEIVERB_DISCARDUNDOSTATE= -6, + OLEIVERB_PROPERTIES = -7, + OLE_E_NOCONNECTION = unchecked((int)0x80040004), + OLE_E_PROMPTSAVECANCELLED = unchecked((int)0x8004000C), + OLEMISC_RECOMPOSEONRESIZE = 0x00000001, + OLEMISC_INSIDEOUT = 0x00000080, + OLEMISC_ACTIVATEWHENVISIBLE = 0x0000100, + OLEMISC_ACTSLIKEBUTTON = 0x00001000, + OLEMISC_SETCLIENTSITEFIRST = 0x00020000, + OBJ_PEN = 1, + OBJ_BRUSH = 2, + OBJ_DC = 3, + OBJ_METADC = 4, + OBJ_PAL = 5, + OBJ_FONT = 6, + OBJ_BITMAP = 7, + OBJ_REGION = 8, + OBJ_METAFILE = 9, + OBJ_MEMDC = 10, + OBJ_EXTPEN = 11, + OBJ_ENHMETADC = 12, + ODS_CHECKED = 0x0008, + ODS_COMBOBOXEDIT = 0x1000, + ODS_DEFAULT = 0x0020, + ODS_DISABLED = 0x0004, + ODS_FOCUS = 0x0010, + ODS_GRAYED = 0x0002, + ODS_HOTLIGHT = 0x0040, + ODS_INACTIVE = 0x0080, + ODS_NOACCEL = 0x0100, + ODS_NOFOCUSRECT = 0x0200, + ODS_SELECTED = 0x0001, + OLECLOSE_SAVEIFDIRTY = 0, + OLECLOSE_PROMPTSAVE = 2; +#endif + + public const int PDERR_SETUPFAILURE = 0x1001, + PDERR_PARSEFAILURE = 0x1002, + PDERR_RETDEFFAILURE = 0x1003, + PDERR_LOADDRVFAILURE = 0x1004, + PDERR_GETDEVMODEFAIL = 0x1005, + PDERR_INITFAILURE = 0x1006, + PDERR_NODEVICES = 0x1007, + PDERR_NODEFAULTPRN = 0x1008, + PDERR_DNDMMISMATCH = 0x1009, + PDERR_CREATEICFAILURE = 0x100A, + PDERR_PRINTERNOTFOUND = 0x100B, + PDERR_DEFAULTDIFFERENT = 0x100C, + PD_ALLPAGES = 0x00000000, + PD_SELECTION = 0x00000001, + PD_PAGENUMS = 0x00000002, + PD_NOSELECTION = 0x00000004, + PD_NOPAGENUMS = 0x00000008, + PD_COLLATE = 0x00000010, + PD_PRINTTOFILE = 0x00000020, + PD_PRINTSETUP = 0x00000040, + PD_NOWARNING = 0x00000080, + PD_RETURNDC = 0x00000100, + PD_RETURNIC = 0x00000200, + PD_RETURNDEFAULT = 0x00000400, + PD_SHOWHELP = 0x00000800, + PD_ENABLEPRINTHOOK = 0x00001000, + PD_ENABLESETUPHOOK = 0x00002000, + PD_ENABLEPRINTTEMPLATE = 0x00004000, + PD_ENABLESETUPTEMPLATE = 0x00008000, + PD_ENABLEPRINTTEMPLATEHANDLE = 0x00010000, + PD_ENABLESETUPTEMPLATEHANDLE = 0x00020000, + PD_USEDEVMODECOPIES = 0x00040000, + PD_USEDEVMODECOPIESANDCOLLATE = 0x00040000, + PD_DISABLEPRINTTOFILE = 0x00080000, + PD_HIDEPRINTTOFILE = 0x00100000, + PD_NONETWORKBUTTON = 0x00200000, + PD_CURRENTPAGE = 0x00400000, + PD_NOCURRENTPAGE = 0x00800000, + PD_EXCLUSIONFLAGS = 0x01000000, + PD_USELARGETEMPLATE = 0x10000000, + PSD_MINMARGINS = 0x00000001, + PSD_MARGINS = 0x00000002, + PSD_INHUNDREDTHSOFMILLIMETERS = 0x00000008, + PSD_DISABLEMARGINS = 0x00000010, + PSD_DISABLEPRINTER = 0x00000020, + PSD_DISABLEORIENTATION = 0x00000100, + PSD_DISABLEPAPER = 0x00000200, + PSD_SHOWHELP = 0x00000800, + PSD_ENABLEPAGESETUPHOOK = 0x00002000, + PSD_NONETWORKBUTTON = 0x00200000, + PS_SOLID = 0, + PS_DOT = 2, + PLANES = 14, + PRF_CHECKVISIBLE = 0x00000001, + PRF_NONCLIENT = 0x00000002, + PRF_CLIENT = 0x00000004, + PRF_ERASEBKGND = 0x00000008, + PRF_CHILDREN = 0x00000010, + PM_NOREMOVE = 0x0000, + PM_REMOVE = 0x0001, + PM_NOYIELD = 0x0002, + PBM_SETRANGE = (0x0400+1), + PBM_SETPOS = (0x0400+2), + PBM_SETSTEP = (0x0400+4), + PBM_SETRANGE32 = (0x0400+6), + PBM_SETBARCOLOR = (0x0400+9), + PBM_SETBKCOLOR = (0x2000 +1), + PSM_SETTITLEA = (0x0400+111), + PSM_SETTITLEW = (0x0400+120), + PSM_SETFINISHTEXTA = (0x0400+115), + PSM_SETFINISHTEXTW = (0x0400+121), + PATCOPY = 0x00F00021, + PATINVERT = 0x005A0049; +#if never + + public const int PBS_SMOOTH = 0x01; +#endif + + public const int QS_KEY = 0x0001, + QS_MOUSEMOVE = 0x0002, + QS_MOUSEBUTTON = 0x0004, + QS_POSTMESSAGE = 0x0008, + QS_TIMER = 0x0010, + QS_PAINT = 0x0020, + QS_SENDMESSAGE = 0x0040, + QS_HOTKEY = 0x0080, + QS_ALLPOSTMESSAGE = 0x0100, + QS_MOUSE = QS_MOUSEMOVE | QS_MOUSEBUTTON, + QS_INPUT = QS_MOUSE | QS_KEY, + QS_ALLEVENTS = QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY, + QS_ALLINPUT = QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY | QS_SENDMESSAGE; +#if never + + //public const int RECO_PASTE = 0x00000000; // paste from clipboard + public const int RECO_DROP = 0x00000001; // drop + //public const int RECO_COPY = 0x00000002; // copy to the clipboard + //public const int RECO_CUT = 0x00000003; // cut to the clipboard + //public const int RECO_DRAG = 0x00000004; // drag + + public const int RPC_E_CHANGED_MODE = unchecked((int)0x80010106), + RGN_AND = 1, + RPC_E_CANTCALLOUT_ININPUTSYNCCALL = unchecked((int)0x8001010D), + RGN_DIFF = 4, +#endif + public const int RDW_INVALIDATE = 0x0001; + public const int RDW_ALLCHILDREN = 0x0080; +#if never + RDW_ERASE = 0x0004, + RDW_FRAME = 0x0400, + RB_INSERTBANDA = (0x0400+1), + RB_INSERTBANDW = (0x0400+10); +#endif + + public const int stc4 = 0x0443, + SHGFP_TYPE_CURRENT = 0, + STGM_READ = 0x00000000, + STGM_WRITE = 0x00000001, + STGM_READWRITE = 0x00000002, + STGM_SHARE_EXCLUSIVE = 0x00000010, + STGM_CREATE = 0x00001000, + STGM_TRANSACTED = 0x00010000, + STGM_CONVERT = 0x00020000, + STGM_DELETEONRELEASE = 0x04000000, + + STGTY_STORAGE = 1, + STGTY_STREAM = 2, + STGTY_LOCKBYTES = 3, + STGTY_PROPERTY = 4, + + STARTF_USESHOWWINDOW = 0x00000001, + SB_HORZ = 0, + SB_VERT = 1, + SB_CTL = 2, + SB_LINEUP = 0, + SB_LINELEFT = 0, + SB_LINEDOWN = 1, + SB_LINERIGHT = 1, + SB_PAGEUP = 2, + SB_PAGELEFT = 2, + SB_PAGEDOWN = 3, + SB_PAGERIGHT = 3, + SB_THUMBPOSITION = 4, + SB_THUMBTRACK = 5, + SB_LEFT = 6, + SB_RIGHT = 7, + SB_ENDSCROLL = 8, + SB_TOP = 6, + SB_BOTTOM = 7, + SIZE_MAXIMIZED = 2, + ESB_ENABLE_BOTH = 0x0000, + ESB_DISABLE_BOTH =0x0003, + SORT_DEFAULT =0x0, + SUBLANG_DEFAULT = 0x01, + SW_HIDE = 0, + SW_NORMAL = 1, + SW_SHOWMINIMIZED = 2, + SW_SHOWMAXIMIZED = 3, + SW_MAXIMIZE = 3, + SW_SHOWNOACTIVATE = 4, + SW_SHOW = 5, + SW_MINIMIZE = 6, + SW_SHOWMINNOACTIVE = 7, + SW_SHOWNA = 8, + SW_RESTORE = 9, + SW_MAX = 10, + SWP_NOSIZE = 0x0001, + SWP_NOMOVE = 0x0002, + SWP_NOZORDER = 0x0004, + SWP_NOACTIVATE = 0x0010, + SWP_SHOWWINDOW = 0x0040, + SWP_HIDEWINDOW = 0x0080, + SWP_DRAWFRAME = 0x0020; +#if never + + public const int SND_SYNC = 0000, + SND_ASYNC = 0x0001, + SND_NODEFAULT = 0x0002, + SND_MEMORY = 0x0004, + SND_LOOP = 0x0008, + SND_PURGE = 0x0040, + SND_FILENAME = 0x00020000, + SND_NOSTOP = 0x0010; +#endif + + public const int MB_ICONHAND = 0x000010, + MB_ICONQUESTION = 0x000020, + MB_ICONEXCLAMATION = 0x000030, + MB_ICONASTERISK = 0x000040; +#if never + + + public const int FLASHW_STOP = 0, + FLASHW_CAPTION = 0x00000001, + FLASHW_TRAY = 0x00000002, + FLASHW_ALL = FLASHW_CAPTION | FLASHW_TRAY, + FLASHW_TIMER = 0x00000004, + FLASHW_TIMERNOFG = 0x0000000C; + + public const int HLP_FILE = 1, + HLP_KEYWORD = 2, + HLP_NAVIGATOR = 3, + HLP_OBJECT = 4; +#endif + + public const int SW_SCROLLCHILDREN = 0x0001, + SW_INVALIDATE = 0x0002, + SW_ERASE = 0x0004, + SW_SMOOTHSCROLL = 0x0010, + SC_SIZE = 0xF000, + SC_MINIMIZE = 0xF020, + SC_MAXIMIZE = 0xF030, + SC_CLOSE = 0xF060, + SC_KEYMENU = 0xF100, + SC_RESTORE = 0xF120, + SC_MOVE = 0xF010, + SS_LEFT = 0x00000000, + SS_CENTER = 0x00000001, + SS_RIGHT = 0x00000002, + SS_OWNERDRAW = 0x0000000D, + SS_NOPREFIX = 0x00000080, + SS_SUNKEN = 0x00001000, + SBS_HORZ = 0x0000, + SBS_VERT = 0x0001, + SIF_RANGE = 0x0001, + SIF_PAGE = 0x0002, + SIF_POS = 0x0004, + SIF_TRACKPOS = 0x0010, + SIF_ALL = (0x0001|0x0002|0x0004|0x0010), + SPI_GETFONTSMOOTHING = 0x004A, + SPI_GETDROPSHADOW = 0x1024, + SPI_GETFLATMENU = 0x1022, + SPI_GETFONTSMOOTHINGTYPE = 0x200A, + SPI_GETFONTSMOOTHINGCONTRAST = 0x200C, + SPI_ICONHORIZONTALSPACING = 0x000D, + SPI_ICONVERTICALSPACING = 0x0018, + SPI_GETICONMETRICS = 0x002D, + SPI_GETICONTITLEWRAP = 0x0019, + SPI_GETICONTITLELOGFONT = 0x001F, + SPI_GETKEYBOARDCUES = 0x100A, + SPI_GETKEYBOARDDELAY = 0x0016, + SPI_GETKEYBOARDPREF = 0x0044, + SPI_GETKEYBOARDSPEED = 0x000A, + SPI_GETMOUSEHOVERWIDTH = 0x0062, + SPI_GETMOUSEHOVERHEIGHT = 0x0064, + SPI_GETMOUSEHOVERTIME = 0x0066, + SPI_GETMOUSESPEED = 0x0070, + SPI_GETMENUDROPALIGNMENT = 0x001B, + SPI_GETMENUFADE = 0x1012, + SPI_GETMENUSHOWDELAY = 0x006A, + SPI_GETCOMBOBOXANIMATION = 0x1004, + SPI_GETCLIENTAREAANIMATION = 0x1042, + SPI_GETGRADIENTCAPTIONS = 0x1008, + SPI_GETHOTTRACKING = 0x100E, + SPI_GETLISTBOXSMOOTHSCROLLING = 0x1006, + SPI_GETMENUANIMATION = 0x1002, + SPI_GETSELECTIONFADE = 0x1014, + SPI_GETTOOLTIPANIMATION = 0x1016, + SPI_GETUIEFFECTS = 0x103E, + SPI_GETACTIVEWINDOWTRACKING = 0x1000, + SPI_GETACTIVEWNDTRKTIMEOUT = 0x2002, + SPI_GETANIMATION = 0x0048, + SPI_GETBORDER = 0x0005, + SPI_GETCARETWIDTH = 0x2006, + SPI_GETMOUSEVANISH = 0x1020, + SPI_GETDRAGFULLWINDOWS = 38, + SPI_GETNONCLIENTMETRICS = 41, + SPI_GETWORKAREA = 48, + SPI_GETHIGHCONTRAST = 66, + SPI_GETDEFAULTINPUTLANG = 89, + SPI_GETSNAPTODEFBUTTON = 95, + SPI_GETWHEELSCROLLLINES = 104, + SBARS_SIZEGRIP = 0x0100, + SB_SETTEXTA = (0x0400+1), + SB_SETTEXTW = (0x0400+11), + SB_GETTEXTA = (0x0400+2), + SB_GETTEXTW = (0x0400+13), + SB_GETTEXTLENGTHA = (0x0400+3), + SB_GETTEXTLENGTHW = (0x0400+12), + SB_SETPARTS = (0x0400+4), + SB_SIMPLE = (0x0400+9), + SB_GETRECT = (0x0400+10), + SB_SETICON = (0x0400+15), + SB_SETTIPTEXTA = (0x0400+16), + SB_SETTIPTEXTW = (0x0400+17), + SB_GETTIPTEXTA = (0x0400+18), + SB_GETTIPTEXTW = (0x0400+19), + SBT_OWNERDRAW = 0x1000, + SBT_NOBORDERS = 0x0100, + SBT_POPOUT = 0x0200, + SBT_RTLREADING = 0x0400, + SRCCOPY = 0x00CC0020, + SRCAND = 0x008800C6, /* dest = source AND dest */ + SRCPAINT = 0x00EE0086, /* dest = source OR dest */ + NOTSRCCOPY = 0x00330008, /* dest = (NOT source) */ + STATFLAG_DEFAULT = 0x0, + STATFLAG_NONAME = 0x1, + STATFLAG_NOOPEN = 0x2, + STGC_DEFAULT = 0x0, + STGC_OVERWRITE = 0x1, + STGC_ONLYIFCURRENT = 0x2, + STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 0x4, + STREAM_SEEK_SET = 0x0, + STREAM_SEEK_CUR = 0x1, + STREAM_SEEK_END = 0x2; + + public const int S_OK = 0x00000000; + public const int S_FALSE = 0x00000001; + + public static bool Succeeded(int hr) { + return(hr >= 0); + } + + public static bool Failed(int hr) { + return(hr < 0); + } + + public const int TRANSPARENT = 1, + OPAQUE = 2, + TME_HOVER = 0x00000001, + TME_LEAVE = 0x00000002, + TPM_LEFTBUTTON = 0x0000, + TPM_RIGHTBUTTON = 0x0002, + TPM_LEFTALIGN = 0x0000, + TPM_RIGHTALIGN = 0x0008, + TPM_VERTICAL = 0x0040, + TV_FIRST = 0x1100, + TBSTATE_CHECKED = 0x01, + TBSTATE_ENABLED = 0x04, + TBSTATE_HIDDEN = 0x08, + TBSTATE_INDETERMINATE = 0x10, + TBSTYLE_BUTTON = 0x00, + TBSTYLE_SEP = 0x01, + TBSTYLE_CHECK = 0x02, + TBSTYLE_DROPDOWN = 0x08, + TBSTYLE_TOOLTIPS = 0x0100, + TBSTYLE_FLAT = 0x0800, + TBSTYLE_LIST = 0x1000, + TBSTYLE_EX_DRAWDDARROWS = 0x00000001, + TB_ENABLEBUTTON = (0x0400+1), + TB_ISBUTTONCHECKED = (0x0400+10), + TB_ISBUTTONINDETERMINATE = (0x0400+13), + TB_ADDBUTTONSA = (0x0400+20), + TB_ADDBUTTONSW = (0x0400+68), + TB_INSERTBUTTONA = (0x0400+21), + TB_INSERTBUTTONW = (0x0400+67), + TB_DELETEBUTTON = (0x0400+22), + TB_GETBUTTON = (0x0400+23), + TB_SAVERESTOREA = (0x0400+26), + TB_SAVERESTOREW = (0x0400+76), + TB_ADDSTRINGA = (0x0400+28), + TB_ADDSTRINGW = (0x0400+77), + TB_BUTTONSTRUCTSIZE = (0x0400+30), + TB_SETBUTTONSIZE = (0x0400+31), + TB_AUTOSIZE = (0x0400+33), + TB_GETROWS = (0x0400+40), + TB_GETBUTTONTEXTA = (0x0400+45), + TB_GETBUTTONTEXTW = (0x0400+75), + TB_SETIMAGELIST = (0x0400+48), + TB_GETRECT = (0x0400+51), + TB_GETBUTTONSIZE = (0x0400+58), + TB_GETBUTTONINFOW = (0x0400+63), + TB_SETBUTTONINFOW = (0x0400+64), + TB_GETBUTTONINFOA = (0x0400+65), + TB_SETBUTTONINFOA = (0x0400+66), + TB_MAPACCELERATORA = (0x0400+78), + TB_SETEXTENDEDSTYLE = (0x0400+84), + TB_MAPACCELERATORW = (0x0400+90), + TB_GETTOOLTIPS = (0x0400 + 35), + TB_SETTOOLTIPS = (0x0400 + 36), + TBIF_IMAGE = 0x00000001, + TBIF_TEXT = 0x00000002, + TBIF_STATE = 0x00000004, + TBIF_STYLE = 0x00000008, + TBIF_COMMAND = 0x00000020, + TBIF_SIZE = 0x00000040, + TBN_GETBUTTONINFOA = ((0-700)-0), + TBN_GETBUTTONINFOW = ((0-700)-20), + TBN_QUERYINSERT = ((0-700)-6), + TBN_DROPDOWN = ((0-700)-10), + TBN_HOTITEMCHANGE = ((0-700)-13), + TBN_GETDISPINFOA = ((0-700)-16), + TBN_GETDISPINFOW = ((0-700)-17), + TBN_GETINFOTIPA = ((0-700)-18), + TBN_GETINFOTIPW = ((0-700)-19), + TTS_ALWAYSTIP = 0x01, + TTS_NOPREFIX =0x02, + TTS_NOANIMATE =0x10, + TTS_NOFADE =0x20, + TTS_BALLOON =0x40, + //TTI_NONE =0, + //TTI_INFO =1, + TTI_WARNING =2, + //TTI_ERROR =3, + TTF_IDISHWND = 0x0001, + TTF_RTLREADING = 0x0004, + TTF_TRACK = 0x0020, + TTF_CENTERTIP = 0x0002, + TTF_SUBCLASS = 0x0010, + TTF_TRANSPARENT = 0x0100, + TTF_ABSOLUTE = 0x0080, + TTDT_AUTOMATIC = 0, + TTDT_RESHOW = 1, + TTDT_AUTOPOP = 2, + TTDT_INITIAL = 3, + TTM_TRACKACTIVATE = (0x0400+17), + TTM_TRACKPOSITION = (0x0400+18), + TTM_ACTIVATE = (0x0400+1), + TTM_POP = (0x0400 + 28), + TTM_ADJUSTRECT = (0x400 + 31), + TTM_SETDELAYTIME = (0x0400+3), +#if !DRT && !UIAUTOMATIONTYPES + TTM_SETTITLEA =((int)WindowMessage.WM_USER + 32), // wParam = TTI_*, lParam = char* szTitle + TTM_SETTITLEW =((int)WindowMessage.WM_USER + 33), // wParam = TTI_*, lParam = wchar* szTitle +#endif + TTM_ADDTOOLA = (0x0400+4), + TTM_ADDTOOLW = (0x0400+50), + TTM_DELTOOLA = (0x0400+5), + TTM_DELTOOLW = (0x0400+51), + TTM_NEWTOOLRECTA = (0x0400+6), + TTM_NEWTOOLRECTW = (0x0400+52), + TTM_RELAYEVENT = (0x0400+7), + TTM_GETTIPBKCOLOR = (0x0400+22), + TTM_SETTIPBKCOLOR = (0x0400 + 19), + TTM_SETTIPTEXTCOLOR = (0x0400 + 20), + TTM_GETTIPTEXTCOLOR = (0x0400+23), + TTM_GETTOOLINFOA = (0x0400+8), + TTM_GETTOOLINFOW = (0x0400+53), + TTM_SETTOOLINFOA = (0x0400+9), + TTM_SETTOOLINFOW = (0x0400+54), + TTM_HITTESTA = (0x0400+10), + TTM_HITTESTW = (0x0400+55), + TTM_GETTEXTA = (0x0400+11), + TTM_GETTEXTW = (0x0400+56), + TTM_UPDATE = (0x0400+29), + TTM_UPDATETIPTEXTA = (0x0400+12), + TTM_UPDATETIPTEXTW = (0x0400+57), + TTM_ENUMTOOLSA = (0x0400+14), + TTM_ENUMTOOLSW = (0x0400+58), + TTM_GETCURRENTTOOLA = (0x0400+15), + TTM_GETCURRENTTOOLW = (0x0400+59), + TTM_WINDOWFROMPOINT = (0x0400+16), + TTM_GETDELAYTIME = (0x0400+21), + TTM_SETMAXTIPWIDTH = (0x0400+24), + TTN_GETDISPINFOA = ((0-520)-0), + TTN_GETDISPINFOW = ((0-520)-10), + TTN_SHOW = ((0-520)-1), + TTN_POP = ((0-520)-2), + TTN_NEEDTEXTA = ((0-520)-0), + TTN_NEEDTEXTW = ((0-520)-10), + TBS_AUTOTICKS = 0x0001, + TBS_VERT = 0x0002, + TBS_TOP = 0x0004, + TBS_BOTTOM = 0x0000, + TBS_BOTH = 0x0008, + TBS_NOTICKS = 0x0010, + TBM_GETPOS = (0x0400), + TBM_SETTIC = (0x0400+4), + TBM_SETPOS = (0x0400+5), + TBM_SETRANGE = (0x0400+6), + TBM_SETRANGEMIN = (0x0400+7), + TBM_SETRANGEMAX = (0x0400+8), + TBM_SETTICFREQ = (0x0400+20), + TBM_SETPAGESIZE = (0x0400+21), + TBM_SETLINESIZE = (0x0400+23), + TB_LINEUP = 0, + TB_LINEDOWN = 1, + TB_PAGEUP = 2, + TB_PAGEDOWN = 3, + TB_THUMBPOSITION = 4, + TB_THUMBTRACK = 5, + TB_TOP = 6, + TB_BOTTOM = 7, + TB_ENDTRACK = 8, + TVS_HASBUTTONS = 0x0001, + TVS_HASLINES = 0x0002, + TVS_LINESATROOT = 0x0004, + TVS_EDITLABELS = 0x0008, + TVS_SHOWSELALWAYS = 0x0020, + TVS_RTLREADING = 0x0040, + TVS_CHECKBOXES = 0x0100, + TVS_TRACKSELECT = 0x0200, + TVS_FULLROWSELECT = 0x1000, + TVS_NONEVENHEIGHT = 0x4000, + TVS_INFOTIP = 0x0800, + TVS_NOTOOLTIPS = 0x0080, + TVIF_TEXT = 0x0001, + TVIF_IMAGE = 0x0002, + TVIF_PARAM = 0x0004, + TVIF_STATE = 0x0008, + TVIF_HANDLE = 0x0010, + TVIF_SELECTEDIMAGE = 0x0020, + TVIS_SELECTED = 0x0002, + TVIS_EXPANDED = 0x0020, + TVIS_EXPANDEDONCE = 0x0040, + TVIS_STATEIMAGEMASK = 0xF000, + TVI_ROOT = (unchecked((int)0xFFFF0000)), + TVI_FIRST = (unchecked((int)0xFFFF0001)), + TVM_INSERTITEMA = (0x1100+0), + TVM_INSERTITEMW = (0x1100+50), + TVM_DELETEITEM = (0x1100+1), + TVM_EXPAND = (0x1100+2), + TVE_COLLAPSE = 0x0001, + TVE_EXPAND = 0x0002, + TVM_GETITEMRECT = (0x1100+4), + TVM_GETINDENT = (0x1100+6), + TVM_SETINDENT = (0x1100+7), + TVM_SETIMAGELIST = (0x1100+9), + TVM_GETNEXTITEM = (0x1100+10), + TVGN_NEXT = 0x0001, + TVGN_PREVIOUS = 0x0002, + TVGN_FIRSTVISIBLE = 0x0005, + TVGN_NEXTVISIBLE = 0x0006, + TVGN_PREVIOUSVISIBLE = 0x0007, + TVGN_CARET = 0x0009, + TVM_SELECTITEM = (0x1100+11), + TVM_GETITEMA = (0x1100+12), + TVM_GETITEMW = (0x1100+62), + TVM_SETITEMA = (0x1100+13), + TVM_SETITEMW = (0x1100+63), + TVM_EDITLABELA = (0x1100+14), + TVM_EDITLABELW = (0x1100+65), + TVM_GETEDITCONTROL = (0x1100+15), + TVM_GETVISIBLECOUNT = (0x1100+16), + TVM_HITTEST = (0x1100+17), + TVM_ENSUREVISIBLE = (0x1100+20), + TVM_ENDEDITLABELNOW = (0x1100+22), + TVM_GETISEARCHSTRINGA = (0x1100+23), + TVM_GETISEARCHSTRINGW = (0x1100+64), + TVM_SETITEMHEIGHT = (0x1100+27), + TVM_GETITEMHEIGHT = (0x1100+28), + TVN_SELCHANGINGA = ((0-400)-1), + TVN_SELCHANGINGW = ((0-400)-50), + TVN_GETINFOTIPA = ((0-400)-13), + TVN_GETINFOTIPW = ((0-400)-14), + TVN_SELCHANGEDA = ((0-400)-2), + TVN_SELCHANGEDW = ((0-400)-51), + TVC_UNKNOWN = 0x0000, + TVC_BYMOUSE = 0x0001, + TVC_BYKEYBOARD = 0x0002, + TVN_GETDISPINFOA = ((0-400)-3), + TVN_GETDISPINFOW = ((0-400)-52), + TVN_SETDISPINFOA = ((0-400)-4), + TVN_SETDISPINFOW = ((0-400)-53), + TVN_ITEMEXPANDINGA = ((0-400)-5), + TVN_ITEMEXPANDINGW = ((0-400)-54), + TVN_ITEMEXPANDEDA = ((0-400)-6), + TVN_ITEMEXPANDEDW = ((0-400)-55), + TVN_BEGINDRAGA = ((0-400)-7), + TVN_BEGINDRAGW = ((0-400)-56), + TVN_BEGINRDRAGA = ((0-400)-8), + TVN_BEGINRDRAGW = ((0-400)-57), + TVN_BEGINLABELEDITA = ((0-400)-10), + TVN_BEGINLABELEDITW = ((0-400)-59), + TVN_ENDLABELEDITA = ((0-400)-11), + TVN_ENDLABELEDITW = ((0-400)-60), + TCS_BOTTOM = 0x0002, + TCS_RIGHT = 0x0002, + TCS_FLATBUTTONS = 0x0008, + TCS_HOTTRACK = 0x0040, + TCS_VERTICAL = 0x0080, + TCS_TABS = 0x0000, + TCS_BUTTONS = 0x0100, + TCS_MULTILINE = 0x0200, + TCS_RIGHTJUSTIFY = 0x0000, + TCS_FIXEDWIDTH = 0x0400, + TCS_RAGGEDRIGHT = 0x0800, + TCS_OWNERDRAWFIXED = 0x2000, + TCS_TOOLTIPS = 0x4000, + TCM_SETIMAGELIST = (0x1300+3), + TCIF_TEXT = 0x0001, + TCIF_IMAGE = 0x0002, + TCM_GETITEMA = (0x1300+5), + TCM_GETITEMW = (0x1300+60), + TCM_SETITEMA = (0x1300+6), + TCM_SETITEMW = (0x1300+61), + TCM_INSERTITEMA = (0x1300+7), + TCM_INSERTITEMW = (0x1300+62), + TCM_DELETEITEM = (0x1300+8), + TCM_DELETEALLITEMS = (0x1300+9), + TCM_GETITEMRECT = (0x1300+10), + TCM_GETCURSEL = (0x1300+11), + TCM_SETCURSEL = (0x1300+12), + TCM_ADJUSTRECT = (0x1300+40), + TCM_SETITEMSIZE = (0x1300+41), + TCM_SETPADDING = (0x1300+43), + TCM_GETROWCOUNT = (0x1300+44), + TCM_GETTOOLTIPS = (0x1300+45), + TCM_SETTOOLTIPS = (0x1300+46), + TCN_SELCHANGE = ((0-550)-1), + TCN_SELCHANGING = ((0-550)-2), + TBSTYLE_WRAPPABLE = 0x0200, + TVM_SETBKCOLOR = (TV_FIRST + 29), + TVM_SETTEXTCOLOR = (TV_FIRST + 30), + TYMED_NULL = 0, + TVM_GETLINECOLOR = (TV_FIRST + 41), + TVM_SETLINECOLOR = (TV_FIRST + 40), + TVM_SETTOOLTIPS = (TV_FIRST + 24), + TVSIL_STATE = 2, + TVM_SORTCHILDRENCB = (TV_FIRST + 21); + + public const int + UIS_SET = 1, + UIS_CLEAR = 2, + UIS_INITIALIZE = 3, + UISF_HIDEFOCUS = 0x1, + UISF_HIDEACCEL = 0x2, + UISF_ACTIVE = 0x4; + +#if never + + public const int TVHT_NOWHERE = 0x0001, + TVHT_ONITEMICON = 0x0002, + TVHT_ONITEMLABEL = 0x0004, + TVHT_ONITEM = (TVHT_ONITEMICON | TVHT_ONITEMLABEL | TVHT_ONITEMSTATEICON), + TVHT_ONITEMINDENT = 0x0008, + TVHT_ONITEMBUTTON = 0x0010, + TVHT_ONITEMRIGHT = 0x0020, + TVHT_ONITEMSTATEICON = 0x0040, + TVHT_ABOVE = 0x0100, + TVHT_BELOW = 0x0200, + TVHT_TORIGHT = 0x0400, + TVHT_TOLEFT = 0x0800; + + public const int + USERCLASSTYPE_FULL = 1, + USERCLASSTYPE_SHORT = 2, + USERCLASSTYPE_APPNAME = 3, + UOI_FLAGS = 1; + + + public const int VIEW_E_DRAW = unchecked((int)0x80040140), + VK_LEFT = 0x25, + VK_UP = 0x26, + VK_RIGHT = 0x27, + VK_DOWN = 0x28, +#endif + + public const int VK_TAB = 0x09; + public const int VK_SHIFT = 0x10; + public const int VK_CONTROL = 0x11; + public const int VK_MENU = 0x12; +#if never + VK_ESCAPE = 0x1B, + VK_INSERT = 0x002D; + + public const int WAVE_FORMAT_PCM = 0x0001, + WAVE_FORMAT_ADPCM = 0x0002, + WAVE_FORMAT_IEEE_FLOAT = 0x0003; + + public const int MMIO_READ = 0x00000000, + MMIO_ALLOCBUF = 0x00010000, + MMIO_FINDRIFF = 0x00000020; +#endif + + public const int WH_JOURNALPLAYBACK = 1, + WH_GETMESSAGE = 3, + WH_MOUSE = 7, + WSF_VISIBLE = 0x0001, + WA_INACTIVE = 0, + WA_ACTIVE = 1, + WA_CLICKACTIVE = 2; + + public const int WHEEL_DELTA = 120, +#if !DRT && !UIAUTOMATIONTYPES + WM_REFLECT = (int)WindowMessage.WM_USER + 0x1C00, + WM_CHOOSEFONT_GETLOGFONT = (int)WindowMessage.WM_USER +1, +#endif + WS_OVERLAPPED = 0x00000000, + WS_POPUP = unchecked((int)0x80000000), + WS_CHILD = 0x40000000, + WS_MINIMIZE = 0x20000000, + WS_VISIBLE = 0x10000000, + WS_DISABLED = 0x08000000, + WS_CLIPSIBLINGS = 0x04000000, + WS_CLIPCHILDREN = 0x02000000, + WS_MAXIMIZE = 0x01000000, + WS_CAPTION = 0x00C00000, + WS_BORDER = 0x00800000, + WS_DLGFRAME = 0x00400000, + WS_VSCROLL = 0x00200000, + WS_HSCROLL = 0x00100000, + WS_SYSMENU = 0x00080000, + WS_THICKFRAME = 0x00040000, + WS_TABSTOP = 0x00010000, + WS_MINIMIZEBOX = 0x00020000, + WS_MAXIMIZEBOX = 0x00010000, + WS_EX_DLGMODALFRAME = 0x00000001, + WS_EX_TRANSPARENT = 0x00000020, + WS_EX_MDICHILD = 0x00000040, + WS_EX_TOOLWINDOW = 0x00000080, + WS_EX_WINDOWEDGE = 0x00000100, + WS_EX_CLIENTEDGE = 0x00000200, + WS_EX_CONTEXTHELP = 0x00000400, + WS_EX_RIGHT = 0x00001000, + WS_EX_LEFT = 0x00000000, + WS_EX_RTLREADING = 0x00002000, + WS_EX_LEFTSCROLLBAR = 0x00004000, + WS_EX_CONTROLPARENT = 0x00010000, + WS_EX_STATICEDGE = 0x00020000, + WS_EX_APPWINDOW = 0x00040000, + WS_EX_LAYERED = 0x00080000, + WS_EX_TOPMOST = 0x00000008, + WS_EX_LAYOUTRTL = 0x00400000, + WS_EX_NOINHERITLAYOUT = 0x00100000, + WS_EX_COMPOSITED = 0x02000000, + WPF_SETMINPOSITION = 0x0001, + WPF_RESTORETOMAXIMIZED = 0x0002; + + public const int WHITE_BRUSH = 0x00000000; + public const int NULL_BRUSH = 5; + +#if never + + public static int START_PAGE_GENERAL = unchecked((int)0xffffffff); + + // Result action ids for PrintDlgEx. + public const int PD_RESULT_CANCEL = 0; + public const int PD_RESULT_PRINT = 1; + public const int PD_RESULT_APPLY = 2; + +#endif + + public const int XBUTTON1 = 0x0001; + public const int XBUTTON2 = 0x0002; +#if never + + + // These are initialized in a static constructor for speed. That way we don't have to + // evaluate the char size each time. + // + public static readonly int CBEM_GETITEM; + public static readonly int CBEM_SETITEM; + public static readonly int CBEN_ENDEDIT; + public static readonly int CBEM_INSERTITEM; + public static readonly int LVM_GETITEMTEXT; + public static readonly int LVM_SETITEMTEXT; + public static readonly int ACM_OPEN; + public static readonly int DTM_SETFORMAT; + public static readonly int DTN_USERSTRING; + public static readonly int DTN_WMKEYDOWN; + public static readonly int DTN_FORMAT; + public static readonly int DTN_FORMATQUERY; + public static readonly int EMR_POLYTEXTOUT; + public static readonly int HDM_INSERTITEM; + public static readonly int HDM_GETITEM; + public static readonly int HDM_SETITEM; + public static readonly int HDN_ITEMCHANGING; + public static readonly int HDN_ITEMCHANGED; + public static readonly int HDN_ITEMCLICK; + public static readonly int HDN_ITEMDBLCLICK; + public static readonly int HDN_DIVIDERDBLCLICK; + public static readonly int HDN_BEGINTRACK; + public static readonly int HDN_ENDTRACK; + public static readonly int HDN_TRACK; + public static readonly int HDN_GETDISPINFO; + public static readonly int LVM_GETITEM; + public static readonly int LVM_SETBKIMAGE; + public static readonly int LVM_SETITEM; + public static readonly int LVM_INSERTITEM; + public static readonly int LVM_FINDITEM; + public static readonly int LVM_GETSTRINGWIDTH; + public static readonly int LVM_EDITLABEL; + public static readonly int LVM_GETCOLUMN; + public static readonly int LVM_SETCOLUMN; + public static readonly int LVM_GETISEARCHSTRING; + public static readonly int LVM_INSERTCOLUMN; + public static readonly int LVN_BEGINLABELEDIT; + public static readonly int LVN_ENDLABELEDIT; + public static readonly int LVN_ODFINDITEM; + public static readonly int LVN_GETDISPINFO; + public static readonly int LVN_GETINFOTIP; + public static readonly int LVN_SETDISPINFO; + public static readonly int PSM_SETTITLE; + public static readonly int PSM_SETFINISHTEXT; + public static readonly int RB_INSERTBAND; + public static readonly int SB_SETTEXT; + public static readonly int SB_GETTEXT; + public static readonly int SB_GETTEXTLENGTH; + public static readonly int SB_SETTIPTEXT; + public static readonly int SB_GETTIPTEXT; + public static readonly int TB_SAVERESTORE; + public static readonly int TB_ADDSTRING; + public static readonly int TB_GETBUTTONTEXT; + public static readonly int TB_MAPACCELERATOR; + public static readonly int TB_GETBUTTONINFO; + public static readonly int TB_SETBUTTONINFO; + public static readonly int TB_INSERTBUTTON; + public static readonly int TB_ADDBUTTONS; + public static readonly int TBN_GETBUTTONINFO; + public static readonly int TBN_GETINFOTIP; + public static readonly int TBN_GETDISPINFO; + public static readonly int TTM_ADDTOOL; + public static readonly int TTM_SETTITLE; + public static readonly int TTM_DELTOOL; + public static readonly int TTM_NEWTOOLRECT; + public static readonly int TTM_GETTOOLINFO; + public static readonly int TTM_SETTOOLINFO; + public static readonly int TTM_HITTEST; + public static readonly int TTM_GETTEXT; + public static readonly int TTM_UPDATETIPTEXT; + public static readonly int TTM_ENUMTOOLS; + public static readonly int TTM_GETCURRENTTOOL; + public static readonly int TTN_GETDISPINFO; + public static readonly int TTN_NEEDTEXT; + public static readonly int TVM_INSERTITEM; + public static readonly int TVM_GETITEM; + public static readonly int TVM_SETITEM; + public static readonly int TVM_EDITLABEL; + public static readonly int TVM_GETISEARCHSTRING; + public static readonly int TVN_SELCHANGING; + public static readonly int TVN_SELCHANGED; + public static readonly int TVN_GETDISPINFO; + public static readonly int TVN_SETDISPINFO; + public static readonly int TVN_ITEMEXPANDING; + public static readonly int TVN_ITEMEXPANDED; + public static readonly int TVN_BEGINDRAG; + public static readonly int TVN_BEGINRDRAG; + public static readonly int TVN_BEGINLABELEDIT; + public static readonly int TVN_ENDLABELEDIT; + public static readonly int TCM_GETITEM; + public static readonly int TCM_SETITEM; + public static readonly int TCM_INSERTITEM; + + public const string TOOLTIPS_CLASS = "tooltips_class32"; + + public const string WC_DATETIMEPICK = "SysDateTimePick32", + WC_LISTVIEW = "SysListView32", + WC_MONTHCAL = "SysMonthCal32", + WC_PROGRESS = "msctls_progress32", + WC_STATUSBAR = "msctls_statusbar32", + WC_TOOLBAR = "ToolbarWindow32", + WC_TRACKBAR = "msctls_trackbar32", + WC_TREEVIEW = "SysTreeView32", + WC_TABCONTROL = "SysTabControl32", + MSH_MOUSEWHEEL = "MSWHEEL_ROLLMSG", + MSH_SCROLL_LINES = "MSH_SCROLL_LINES_MSG", + MOUSEZ_CLASSNAME = "MouseZ", + MOUSEZ_TITLE = "Magellan MSWHEEL"; + + public const int CHILDID_SELF = 0; + + public const int OBJID_QUERYCLASSNAMEIDX = unchecked(unchecked((int)0xFFFFFFF4)); + public const int OBJID_WINDOW = unchecked(unchecked((int)0x00000000)); + + public const string uuid_IAccessible = "{618736E0-3C3D-11CF-810C-00AA00389B71}"; + public const string uuid_IEnumVariant = "{00020404-0000-0000-C000-000000000046}"; + + static NativeMethods() { + if (Marshal.SystemDefaultCharSize == 1) { + CBEM_GETITEM = NativeMethods.CBEM_GETITEMA; + CBEM_SETITEM = NativeMethods.CBEM_SETITEMA; + CBEN_ENDEDIT = NativeMethods.CBEN_ENDEDITA; + CBEM_INSERTITEM = NativeMethods.CBEM_INSERTITEMA; + LVM_GETITEMTEXT = NativeMethods.LVM_GETITEMTEXTA; + LVM_SETITEMTEXT = NativeMethods.LVM_SETITEMTEXTA; + ACM_OPEN = NativeMethods.ACM_OPENA; + DTM_SETFORMAT = NativeMethods.DTM_SETFORMATA; + DTN_USERSTRING = NativeMethods.DTN_USERSTRINGA; + DTN_WMKEYDOWN = NativeMethods.DTN_WMKEYDOWNA; + DTN_FORMAT = NativeMethods.DTN_FORMATA; + DTN_FORMATQUERY = NativeMethods.DTN_FORMATQUERYA; + EMR_POLYTEXTOUT = NativeMethods.EMR_POLYTEXTOUTA; + HDM_INSERTITEM = NativeMethods.HDM_INSERTITEMA; + HDM_GETITEM = NativeMethods.HDM_GETITEMA; + HDM_SETITEM = NativeMethods.HDM_SETITEMA; + HDN_ITEMCHANGING = NativeMethods.HDN_ITEMCHANGINGA; + HDN_ITEMCHANGED = NativeMethods.HDN_ITEMCHANGEDA; + HDN_ITEMCLICK = NativeMethods.HDN_ITEMCLICKA; + HDN_ITEMDBLCLICK = NativeMethods.HDN_ITEMDBLCLICKA; + HDN_DIVIDERDBLCLICK = NativeMethods.HDN_DIVIDERDBLCLICKA; + HDN_BEGINTRACK = NativeMethods.HDN_BEGINTRACKA; + HDN_ENDTRACK = NativeMethods.HDN_ENDTRACKA; + HDN_TRACK = NativeMethods.HDN_TRACKA; + HDN_GETDISPINFO = NativeMethods.HDN_GETDISPINFOA; + LVM_SETBKIMAGE = NativeMethods.LVM_SETBKIMAGEA; + LVM_GETITEM = NativeMethods.LVM_GETITEMA; + LVM_SETITEM = NativeMethods.LVM_SETITEMA; + LVM_INSERTITEM = NativeMethods.LVM_INSERTITEMA; + LVM_FINDITEM = NativeMethods.LVM_FINDITEMA; + LVM_GETSTRINGWIDTH = NativeMethods.LVM_GETSTRINGWIDTHA; + LVM_EDITLABEL = NativeMethods.LVM_EDITLABELA; + LVM_GETCOLUMN = NativeMethods.LVM_GETCOLUMNA; + LVM_SETCOLUMN = NativeMethods.LVM_SETCOLUMNA; + LVM_GETISEARCHSTRING = NativeMethods.LVM_GETISEARCHSTRINGA; + LVM_INSERTCOLUMN = NativeMethods.LVM_INSERTCOLUMNA; + LVN_BEGINLABELEDIT = NativeMethods.LVN_BEGINLABELEDITA; + LVN_ENDLABELEDIT = NativeMethods.LVN_ENDLABELEDITA; + LVN_ODFINDITEM = NativeMethods.LVN_ODFINDITEMA; + LVN_GETDISPINFO = NativeMethods.LVN_GETDISPINFOA; + LVN_GETINFOTIP = NativeMethods.LVN_GETINFOTIPA; + LVN_SETDISPINFO = NativeMethods.LVN_SETDISPINFOA; + PSM_SETTITLE = NativeMethods.PSM_SETTITLEA; + PSM_SETFINISHTEXT = NativeMethods.PSM_SETFINISHTEXTA; + RB_INSERTBAND = NativeMethods.RB_INSERTBANDA; + SB_SETTEXT = NativeMethods.SB_SETTEXTA; + SB_GETTEXT = NativeMethods.SB_GETTEXTA; + SB_GETTEXTLENGTH = NativeMethods.SB_GETTEXTLENGTHA; + SB_SETTIPTEXT = NativeMethods.SB_SETTIPTEXTA; + SB_GETTIPTEXT = NativeMethods.SB_GETTIPTEXTA; + TB_SAVERESTORE = NativeMethods.TB_SAVERESTOREA; + TB_ADDSTRING = NativeMethods.TB_ADDSTRINGA; + TB_GETBUTTONTEXT = NativeMethods.TB_GETBUTTONTEXTA; + TB_MAPACCELERATOR = NativeMethods.TB_MAPACCELERATORA; + TB_GETBUTTONINFO = NativeMethods.TB_GETBUTTONINFOA; + TB_SETBUTTONINFO = NativeMethods.TB_SETBUTTONINFOA; + TB_INSERTBUTTON = NativeMethods.TB_INSERTBUTTONA; + TB_ADDBUTTONS = NativeMethods.TB_ADDBUTTONSA; + TBN_GETBUTTONINFO = NativeMethods.TBN_GETBUTTONINFOA; + TBN_GETINFOTIP = NativeMethods.TBN_GETINFOTIPA; + TBN_GETDISPINFO = NativeMethods.TBN_GETDISPINFOA; + TTM_ADDTOOL = NativeMethods.TTM_ADDTOOLA; + TTM_SETTITLE = NativeMethods.TTM_SETTITLEA; + TTM_DELTOOL = NativeMethods.TTM_DELTOOLA; + TTM_NEWTOOLRECT = NativeMethods.TTM_NEWTOOLRECTA; + TTM_GETTOOLINFO = NativeMethods.TTM_GETTOOLINFOA; + TTM_SETTOOLINFO = NativeMethods.TTM_SETTOOLINFOA; + TTM_HITTEST = NativeMethods.TTM_HITTESTA; + TTM_GETTEXT = NativeMethods.TTM_GETTEXTA; + TTM_UPDATETIPTEXT = NativeMethods.TTM_UPDATETIPTEXTA; + TTM_ENUMTOOLS = NativeMethods.TTM_ENUMTOOLSA; + TTM_GETCURRENTTOOL = NativeMethods.TTM_GETCURRENTTOOLA; + TTN_GETDISPINFO = NativeMethods.TTN_GETDISPINFOA; + TTN_NEEDTEXT = NativeMethods.TTN_NEEDTEXTA; + TVM_INSERTITEM = NativeMethods.TVM_INSERTITEMA; + TVM_GETITEM = NativeMethods.TVM_GETITEMA; + TVM_SETITEM = NativeMethods.TVM_SETITEMA; + TVM_EDITLABEL = NativeMethods.TVM_EDITLABELA; + TVM_GETISEARCHSTRING = NativeMethods.TVM_GETISEARCHSTRINGA; + TVN_SELCHANGING = NativeMethods.TVN_SELCHANGINGA; + TVN_SELCHANGED = NativeMethods.TVN_SELCHANGEDA; + TVN_GETDISPINFO = NativeMethods.TVN_GETDISPINFOA; + TVN_SETDISPINFO = NativeMethods.TVN_SETDISPINFOA; + TVN_ITEMEXPANDING = NativeMethods.TVN_ITEMEXPANDINGA; + TVN_ITEMEXPANDED = NativeMethods.TVN_ITEMEXPANDEDA; + TVN_BEGINDRAG = NativeMethods.TVN_BEGINDRAGA; + TVN_BEGINRDRAG = NativeMethods.TVN_BEGINRDRAGA; + TVN_BEGINLABELEDIT = NativeMethods.TVN_BEGINLABELEDITA; + TVN_ENDLABELEDIT = NativeMethods.TVN_ENDLABELEDITA; + TCM_GETITEM = NativeMethods.TCM_GETITEMA; + TCM_SETITEM = NativeMethods.TCM_SETITEMA; + TCM_INSERTITEM = NativeMethods.TCM_INSERTITEMA; + } + else { + CBEM_GETITEM = NativeMethods.CBEM_GETITEMW; + CBEM_SETITEM = NativeMethods.CBEM_SETITEMW; + CBEN_ENDEDIT = NativeMethods.CBEN_ENDEDITW; + CBEM_INSERTITEM = NativeMethods.CBEM_INSERTITEMW; + LVM_GETITEMTEXT = NativeMethods.LVM_GETITEMTEXTW; + LVM_SETITEMTEXT = NativeMethods.LVM_SETITEMTEXTW; + ACM_OPEN = NativeMethods.ACM_OPENW; + DTM_SETFORMAT = NativeMethods.DTM_SETFORMATW; + DTN_USERSTRING = NativeMethods.DTN_USERSTRINGW; + DTN_WMKEYDOWN = NativeMethods.DTN_WMKEYDOWNW; + DTN_FORMAT = NativeMethods.DTN_FORMATW; + DTN_FORMATQUERY = NativeMethods.DTN_FORMATQUERYW; + EMR_POLYTEXTOUT = NativeMethods.EMR_POLYTEXTOUTW; + HDM_INSERTITEM = NativeMethods.HDM_INSERTITEMW; + HDM_GETITEM = NativeMethods.HDM_GETITEMW; + HDM_SETITEM = NativeMethods.HDM_SETITEMW; + HDN_ITEMCHANGING = NativeMethods.HDN_ITEMCHANGINGW; + HDN_ITEMCHANGED = NativeMethods.HDN_ITEMCHANGEDW; + HDN_ITEMCLICK = NativeMethods.HDN_ITEMCLICKW; + HDN_ITEMDBLCLICK = NativeMethods.HDN_ITEMDBLCLICKW; + HDN_DIVIDERDBLCLICK = NativeMethods.HDN_DIVIDERDBLCLICKW; + HDN_BEGINTRACK = NativeMethods.HDN_BEGINTRACKW; + HDN_ENDTRACK = NativeMethods.HDN_ENDTRACKW; + HDN_TRACK = NativeMethods.HDN_TRACKW; + HDN_GETDISPINFO = NativeMethods.HDN_GETDISPINFOW; + LVM_SETBKIMAGE = NativeMethods.LVM_SETBKIMAGEW; + LVM_GETITEM = NativeMethods.LVM_GETITEMW; + LVM_SETITEM = NativeMethods.LVM_SETITEMW; + LVM_INSERTITEM = NativeMethods.LVM_INSERTITEMW; + LVM_FINDITEM = NativeMethods.LVM_FINDITEMW; + LVM_GETSTRINGWIDTH = NativeMethods.LVM_GETSTRINGWIDTHW; + LVM_EDITLABEL = NativeMethods.LVM_EDITLABELW; + LVM_GETCOLUMN = NativeMethods.LVM_GETCOLUMNW; + LVM_SETCOLUMN = NativeMethods.LVM_SETCOLUMNW; + LVM_GETISEARCHSTRING = NativeMethods.LVM_GETISEARCHSTRINGW; + LVM_INSERTCOLUMN = NativeMethods.LVM_INSERTCOLUMNW; + LVN_BEGINLABELEDIT = NativeMethods.LVN_BEGINLABELEDITW; + LVN_ENDLABELEDIT = NativeMethods.LVN_ENDLABELEDITW; + LVN_ODFINDITEM = NativeMethods.LVN_ODFINDITEMW; + LVN_GETDISPINFO = NativeMethods.LVN_GETDISPINFOW; + LVN_GETINFOTIP = NativeMethods.LVN_GETINFOTIPW; + LVN_SETDISPINFO = NativeMethods.LVN_SETDISPINFOW; + PSM_SETTITLE = NativeMethods.PSM_SETTITLEW; + PSM_SETFINISHTEXT = NativeMethods.PSM_SETFINISHTEXTW; + RB_INSERTBAND = NativeMethods.RB_INSERTBANDW; + SB_SETTEXT = NativeMethods.SB_SETTEXTW; + SB_GETTEXT = NativeMethods.SB_GETTEXTW; + SB_GETTEXTLENGTH = NativeMethods.SB_GETTEXTLENGTHW; + SB_SETTIPTEXT = NativeMethods.SB_SETTIPTEXTW; + SB_GETTIPTEXT = NativeMethods.SB_GETTIPTEXTW; + TB_SAVERESTORE = NativeMethods.TB_SAVERESTOREW; + TB_ADDSTRING = NativeMethods.TB_ADDSTRINGW; + TB_GETBUTTONTEXT = NativeMethods.TB_GETBUTTONTEXTW; + TB_MAPACCELERATOR = NativeMethods.TB_MAPACCELERATORW; + TB_GETBUTTONINFO = NativeMethods.TB_GETBUTTONINFOW; + TB_SETBUTTONINFO = NativeMethods.TB_SETBUTTONINFOW; + TB_INSERTBUTTON = NativeMethods.TB_INSERTBUTTONW; + TB_ADDBUTTONS = NativeMethods.TB_ADDBUTTONSW; + TBN_GETBUTTONINFO = NativeMethods.TBN_GETBUTTONINFOW; + TBN_GETINFOTIP = NativeMethods.TBN_GETINFOTIPW; + TBN_GETDISPINFO = NativeMethods.TBN_GETDISPINFOW; + TTM_ADDTOOL = NativeMethods.TTM_ADDTOOLW; + TTM_SETTITLE = NativeMethods.TTM_SETTITLEW; + TTM_DELTOOL = NativeMethods.TTM_DELTOOLW; + TTM_NEWTOOLRECT = NativeMethods.TTM_NEWTOOLRECTW; + TTM_GETTOOLINFO = NativeMethods.TTM_GETTOOLINFOW; + TTM_SETTOOLINFO = NativeMethods.TTM_SETTOOLINFOW; + TTM_HITTEST = NativeMethods.TTM_HITTESTW; + TTM_GETTEXT = NativeMethods.TTM_GETTEXTW; + TTM_UPDATETIPTEXT = NativeMethods.TTM_UPDATETIPTEXTW; + TTM_ENUMTOOLS = NativeMethods.TTM_ENUMTOOLSW; + TTM_GETCURRENTTOOL = NativeMethods.TTM_GETCURRENTTOOLW; + TTN_GETDISPINFO = NativeMethods.TTN_GETDISPINFOW; + TTN_NEEDTEXT = NativeMethods.TTN_NEEDTEXTW; + TVM_INSERTITEM = NativeMethods.TVM_INSERTITEMW; + TVM_GETITEM = NativeMethods.TVM_GETITEMW; + TVM_SETITEM = NativeMethods.TVM_SETITEMW; + TVM_EDITLABEL = NativeMethods.TVM_EDITLABELW; + TVM_GETISEARCHSTRING = NativeMethods.TVM_GETISEARCHSTRINGW; + TVN_SELCHANGING = NativeMethods.TVN_SELCHANGINGW; + TVN_SELCHANGED = NativeMethods.TVN_SELCHANGEDW; + TVN_GETDISPINFO = NativeMethods.TVN_GETDISPINFOW; + TVN_SETDISPINFO = NativeMethods.TVN_SETDISPINFOW; + TVN_ITEMEXPANDING = NativeMethods.TVN_ITEMEXPANDINGW; + TVN_ITEMEXPANDED = NativeMethods.TVN_ITEMEXPANDEDW; + TVN_BEGINDRAG = NativeMethods.TVN_BEGINDRAGW; + TVN_BEGINRDRAG = NativeMethods.TVN_BEGINRDRAGW; + TVN_BEGINLABELEDIT = NativeMethods.TVN_BEGINLABELEDITW; + TVN_ENDLABELEDIT = NativeMethods.TVN_ENDLABELEDITW; + TCM_GETITEM = NativeMethods.TCM_GETITEMW; + TCM_SETITEM = NativeMethods.TCM_SETITEMW; + TCM_INSERTITEM = NativeMethods.TCM_INSERTITEMW; + } + } + + /* + * MISCELLANEOUS + */ + + + [StructLayout(LayoutKind.Sequential), CLSCompliant(false)] + public class OLECMD { + [MarshalAs(UnmanagedType.U4)] + public uint cmdID; + [MarshalAs(UnmanagedType.U4)] + public uint cmdf; + } + + /// + /// Critical : Elevates to UnmanagedCode permissions + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComVisible(true), ComImport(), Guid("B722BCCB-4E68-101B-A2BC-00AA00404770"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown), CLSCompliantAttribute(false)] + public interface IOleCommandTarget + { + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int QueryStatus( + ref Guid pguidCmdGroup, + int cCmds, + [In, Out] + OLECMD prgCmds, + [In, Out] + IntPtr pCmdText); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int Exec( + ref Guid pguidCmdGroup, + int nCmdID, + int nCmdexecopt, + // we need to have this an array because callers need to be able to specify NULL or VT_NULL + [In, MarshalAs(UnmanagedType.LPArray)] + Object[] pvaIn, + int pvaOut); + } +#endif + public static int SignedHIWORD(int n) + { + int i = (int)(short)((n >> 16) & 0xffff); + + return i; + } + + public static int SignedLOWORD(int n) + { + int i = (int)(short)(n & 0xFFFF); + + return i; + } +#if never + + /// + /// + /// This is a new class used in Imagelist to get the system Imagelist List for Small and Large Icons. + /// + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class SHFILEINFO { + public IntPtr hIcon; + public int iIcon; + public int cbWndExtra; + public int dwAttributes; + public string szDisplayName; + public string szTyoeName; + } + + + /// + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + public class FONTDESC { + public int cbSizeOfStruct = SizeOf(); + public string lpstrName; + public long cySize; + public short sWeight; + public short sCharset; + public bool fItalic; + public bool fUnderline; + public bool fStrikethrough; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(FONTDESC)); + } + } + + + /// + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + public class FLASHWINFO { + public int cbSize = SizeOf(); + public IntPtr hWnd; + public int dwFlags; + public int uCount; + public int dwTimeOut; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(FLASHWINFO)); + } + } + + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public class PICTDESCbmp { + internal int cbSizeOfStruct = SizeOf(); + internal int picType = Ole.PICTYPE_BITMAP; + internal IntPtr hbitmap = IntPtr.Zero; + internal IntPtr hpalette = IntPtr.Zero; + internal int unused = 0; + + public PICTDESCbmp(System.Drawing.Bitmap bitmap) { + hbitmap = bitmap.GetHbitmap(); + // gpr: What about palettes? + } + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(PICTDESCbmp)); + } + } + + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public class PICTDESCicon { + internal int cbSizeOfStruct = SizeOf(); + internal int picType = Ole.PICTYPE_ICON; + internal IntPtr hicon = IntPtr.Zero; + internal int unused1 = 0; + internal int unused2 = 0; + + public PICTDESCicon(System.Drawing.Icon icon) { + hicon = SafeNativeMethods.CopyImage(new HandleRef(icon, icon.Handle), NativeMethods.IMAGE_ICON, icon.Size.Width, icon.Size.Height, 0); + } + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(PICTDESCicon)); + } + } + + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public class PICTDESCemf { + internal int cbSizeOfStruct = SizeOf(); + internal int picType = Ole.PICTYPE_ENHMETAFILE; + internal IntPtr hemf = IntPtr.Zero; + internal int unused1 = 0; + internal int unused2 = 0; + + public PICTDESCemf(System.Drawing.Imaging.Metafile metafile) { + //gpr hemf = metafile.CopyHandle(); + } + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(PICTDESCemf)); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class USEROBJECTFLAGS { + public int fInherit = 0; + public int fReserved = 0; + public int dwFlags = 0; + } + + [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)] + internal class SYSTEMTIMEARRAY { + public short wYear1; + public short wMonth1; + public short wDayOfWeek1; + public short wDay1; + public short wHour1; + public short wMinute1; + public short wSecond1; + public short wMilliseconds1; + public short wYear2; + public short wMonth2; + public short wDayOfWeek2; + public short wDay2; + public short wHour2; + public short wMinute2; + public short wSecond2; + public short wMilliseconds2; + } + + public delegate bool EnumChildrenCallback(IntPtr hwnd, IntPtr lParam); + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class HH_AKLINK { + internal int cbStruct=SizeOf(); + internal bool fReserved; + internal string pszKeywords; + internal string pszUrl; + internal string pszMsgText; + internal string pszMsgTitle; + internal string pszWindow; + internal bool fIndexOnFail; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(HH_AKLINK)); + } + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class HH_POPUP { + internal int cbStruct=SizeOf(); + internal IntPtr hinst = IntPtr.Zero; + internal int idString = 0; + internal IntPtr pszText; + internal POINT pt; + internal int clrForeground = -1; + internal int clrBackground = -1; + internal RECT rcMargins = RECT.FromXYWH(-1, -1, -1, -1); // amount of space between edges of window and text, -1 for each member to ignore + internal string pszFont = null; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(HH_POPUP)); + } + } + + public static readonly int HH_FTS_DEFAULT_PROXIMITY = -1; + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class HH_FTS_QUERY { + internal int cbStruct = SizeOf(); + internal bool fUniCodeStrings; + [MarshalAs(UnmanagedType.LPStr)] + internal string pszSearchQuery; + internal int iProximity = NativeMethods.HH_FTS_DEFAULT_PROXIMITY; + internal bool fStemmedSearch; + internal bool fTitleOnly; + internal bool fExecute = true; + [MarshalAs(UnmanagedType.LPStr)] + internal string pszWindow; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(HH_FTS_QUERY)); + } + } +#endif + + [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto, Pack=4)] + public class MONITORINFOEX { + internal int cbSize = SizeOf(); + internal RECT rcMonitor = new RECT(); + internal RECT rcWork = new RECT(); + internal int dwFlags = 0; + [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)] + internal char[] szDevice = new char[32]; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(MONITORINFOEX)); + } + } +#if never + [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto, Pack=4)] + public class MONITORINFO { + internal int cbSize = SizeOf(); + internal RECT rcMonitor = new RECT(); + internal RECT rcWork = new RECT(); + internal int dwFlags = 0; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(MONITORINFO)); + } + } + + public delegate bool EnumChildrenProc(IntPtr hwnd, IntPtr lParam); + public delegate int EditStreamCallback(IntPtr dwCookie, IntPtr buf, int cb, out int transferred); + + [StructLayout(LayoutKind.Sequential)] + public class EDITSTREAM { + public IntPtr dwCookie = IntPtr.Zero; + public int dwError = 0; + public EditStreamCallback pfnCallback = null; + } + + [StructLayout(LayoutKind.Sequential)] + public class EDITSTREAM64 { + [MarshalAs(UnmanagedType.ByValArray, SizeConst=20)] + public byte[] contents = new byte[20]; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public struct DEVMODE + { + private const int CCHDEVICENAME = 32; + private const int CCHFORMNAME = 32; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)] + public string dmDeviceName; + public short dmSpecVersion; + public short dmDriverVersion; + public short dmSize; + public short dmDriverExtra; + public int dmFields; + public int dmPositionX; + public int dmPositionY; + public ScreenOrientation dmDisplayOrientation; + public int dmDisplayFixedOutput; + public short dmColor; + public short dmDuplex; + public short dmYResolution; + public short dmTTOption; + public short dmCollate; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)] + public string dmFormName; + public short dmLogPixels; + public int dmBitsPerPel; + public int dmPelsWidth; + public int dmPelsHeight; + public int dmDisplayFlags; + public int dmDisplayFrequency; + public int dmICMMethod; + public int dmICMIntent; + public int dmMediaType; + public int dmDitherType; + public int dmReserved1; + public int dmReserved2; + public int dmPanningWidth; + public int dmPanningHeight; + } + + /// + /// Critical : Elevates to UnmanagedCode permissions + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("0FF510A3-5FA5-49F1-8CCC-190D71083F3E"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IVsPerPropertyBrowsing { + // hides the property at the given dispid from the properties window + // implmentors should can return E_NOTIMPL to show all properties that + // are otherwise browsable. + + [PreserveSig] + int HideProperty(int dispid,ref bool pfHide); + + // will have the "+" expandable glyph next to them and can be expanded or collapsed by the user + // Returning a non-S_OK return code or false for pfDisplay will suppress this feature + + [PreserveSig] + int DisplayChildProperties(int dispid, + ref bool pfDisplay); + + // retrieves the localized name and description for a property. + // returning a non-S_OK return code will display the default values + + [PreserveSig] + int GetLocalizedPropertyInfo(int dispid, int localeID, + [Out, MarshalAs(UnmanagedType.LPArray)] + string[] pbstrLocalizedName, + [Out, MarshalAs(UnmanagedType.LPArray)] + string[] pbstrLocalizeDescription); + + // determines if the given (usually current) value for a property is the default. If it is not default, + // the property will be shown as bold in the browser to indcate that it has been modified from the default. + + [PreserveSig] + int HasDefaultValue(int dispid, + ref bool fDefault); + + // determines if a property should be made read only. This only applies to properties that are writeable, + [PreserveSig] + int IsPropertyReadOnly(int dispid, + ref bool fReadOnly); + + + // returns the classname for this object. The class name is the non-bolded text that appears in the + // properties window selection combo. If this method returns a non-S_OK return code, the default + // will be used. The default is the name string from a call to ITypeInfo::GetDocumentation(MEMID_NIL, ...); + [PreserveSig] + int GetClassName([In, Out]ref string pbstrClassName); + + // checks whether the given property can be reset to some default value. If return value is non-S_OK or *pfCanReset is + // + [PreserveSig] + int CanResetPropertyValue(int dispid, [In, Out]ref bool pfCanReset); + + // given property. If the return value is S_OK, the property's value will then be refreshed to the new default + // values. + [PreserveSig] + int ResetPropertyValue(int dispid); + } + + /// + /// Critical : Elevates to UnmanagedCode permissions + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("7494683C-37A0-11d2-A273-00C04F8EF4FF"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IManagedPerPropertyBrowsing { + + + [PreserveSig] + int GetPropertyAttributes(int dispid, + ref int pcAttributes, + ref IntPtr pbstrAttrNames, + ref IntPtr pvariantInitValues); + } + + /// + /// Critical : Elevates to UnmanagedCode permissions + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("33C0C1D8-33CF-11d3-BFF2-00C04F990235"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IProvidePropertyBuilder { + + [PreserveSig] + int MapPropertyToBuilder( + int dispid, + [In, Out, MarshalAs(UnmanagedType.LPArray)] + int[] pdwCtlBldType, + [In, Out, MarshalAs(UnmanagedType.LPArray)] + string[] pbstrGuidBldr, + + [In, Out, MarshalAs(UnmanagedType.Bool)] + ref bool builderAvailable); + + [PreserveSig] + int ExecuteBuilder( + int dispid, + [In, MarshalAs(UnmanagedType.BStr)] + string bstrGuidBldr, + [In, MarshalAs(UnmanagedType.Interface)] + object pdispApp, + + HandleRef hwndBldrOwner, + [Out, In, MarshalAs(UnmanagedType.Struct)] + ref object pvarValue, + [In, Out, MarshalAs(UnmanagedType.Bool)] + ref bool actionCommitted); + } + + [StructLayout(LayoutKind.Sequential)] + public class INITCOMMONCONTROLSEX { + public int dwSize = SizeOf(); + public int dwICC; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(MONITORINFO)); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class IMAGELISTDRAWPARAMS { + public int cbSize = SizeOf(); + public IntPtr himl; + public int i; + public IntPtr hdcDst; + public int x; + public int y; + public int cx; + public int cy; + public int xBitmap; + public int yBitmap; + public int rgbBk; + public int rgbFg; + public int fStyle; + public int dwRop; + public int fState; + public int Frame; + public int crEffect; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(IMAGELISTDRAWPARAMS)); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class IMAGEINFO { + public IntPtr hbmImage; + public IntPtr hbmMask; + public int Unused1; + public int Unused2; + // rcImage was a by-value RECT structure + public int rcImage_left; + public int rcImage_top; + public int rcImage_right; + public int rcImage_bottom; + } +#endif + + [StructLayout(LayoutKind.Sequential)] + public class TRACKMOUSEEVENT { + public int cbSize = SizeOf(); + public int dwFlags = 0; + public IntPtr hwndTrack = IntPtr.Zero; + public int dwHoverTime = 100; // Never set this to field ZERO, or to HOVER_DEFAULT, ever! + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(TRACKMOUSEEVENT)); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class POINT { + public int x; + public int y; + + public POINT() { + } + + public POINT(int x, int y) { + this.x = x; + this.y = y; + } +#if DEBUG + public override string ToString() { + return "{x=" + x + ", y=" + y + "}"; + } +#endif + } + + // use this in cases where the Native API takes a POINT not a POINT* + // classes marshal by ref. + [StructLayout(LayoutKind.Sequential)] + public struct POINTSTRUCT { + public int x; + public int y; + public POINTSTRUCT(int x, int y) { + this.x = x; + this.y = y; + } + } + + public delegate IntPtr WndProc(IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam); + + +#if never + [StructLayout(LayoutKind.Sequential)] + public struct RECT { + public int left; + public int top; + public int right; + public int bottom; + + public RECT(int left, int top, int right, int bottom) { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } + + public RECT(System.Drawing.Rectangle r) { + this.left = r.Left; + this.top = r.Top; + this.right = r.Right; + this.bottom = r.Bottom; + } + + public static RECT FromXYWH(int x, int y, int width, int height) { + return new RECT(x, y, x + width, y + height); + } + + public System.Drawing.Size Size { + get { + return new System.Drawing.Size(this.right - this.left, this.bottom - this.top); + } + } + } +#endif + [StructLayout(LayoutKind.Sequential)] + public struct MARGINS { + public int cxLeftWidth; + public int cxRightWidth; + public int cyTopHeight; + public int cyBottomHeight; + } +#if never + + public delegate int ListViewCompareCallback(IntPtr lParam1, IntPtr lParam2, IntPtr lParamSort); + + public delegate int TreeViewCompareCallback(IntPtr lParam1, IntPtr lParam2, IntPtr lParamSort); + + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class WNDCLASS { + public int style = 0; + public IntPtr lpfnWndProc = IntPtr.Zero; + public int cbClsExtra = 0; + public int cbWndExtra = 0; + public IntPtr hInstance = IntPtr.Zero; + public IntPtr hIcon = IntPtr.Zero; + public IntPtr hCursor = IntPtr.Zero; + public IntPtr hbrBackground = IntPtr.Zero; + public string lpszMenuName = null; + public string lpszClassName = null; + } + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class WNDCLASS_I { + public int style = 0; + public IntPtr lpfnWndProc = IntPtr.Zero; + public int cbClsExtra = 0; + public int cbWndExtra = 0; + public IntPtr hInstance = IntPtr.Zero; + public IntPtr hIcon = IntPtr.Zero; + public IntPtr hCursor = IntPtr.Zero; + public IntPtr hbrBackground = IntPtr.Zero; + public IntPtr lpszMenuName = IntPtr.Zero; + public IntPtr lpszClassName = IntPtr.Zero; + } +#endif + + [StructLayout(LayoutKind.Sequential)] + public class NONCLIENTMETRICS { + public int cbSize = SizeOf(); + public int iBorderWidth = 0; + public int iScrollWidth = 0; + public int iScrollHeight = 0; + public int iCaptionWidth = 0; + public int iCaptionHeight = 0; + [MarshalAs(UnmanagedType.Struct)] + public LOGFONT lfCaptionFont = null; + public int iSmCaptionWidth = 0; + public int iSmCaptionHeight = 0; + [MarshalAs(UnmanagedType.Struct)] + public LOGFONT lfSmCaptionFont = null; + public int iMenuWidth = 0; + public int iMenuHeight = 0; + [MarshalAs(UnmanagedType.Struct)] + public LOGFONT lfMenuFont = null; + [MarshalAs(UnmanagedType.Struct)] + public LOGFONT lfStatusFont = null; + [MarshalAs(UnmanagedType.Struct)] + public LOGFONT lfMessageFont = null; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(NONCLIENTMETRICS)); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class ICONMETRICS { + public int cbSize = SizeOf(); + public int iHorzSpacing = 0; + public int iVertSpacing = 0; + public int iTitleWrap = 0; + [MarshalAs(UnmanagedType.Struct)] + public LOGFONT lfFont = null; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(ICONMETRICS)); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct PAINTSTRUCT { + public IntPtr hdc; + public bool fErase; + // rcPaint was a by-value RECT structure + public int rcPaint_left; + public int rcPaint_top; + public int rcPaint_right; + public int rcPaint_bottom; + public bool fRestore; + public bool fIncUpdate; + public int reserved1; + public int reserved2; + public int reserved3; + public int reserved4; + public int reserved5; + public int reserved6; + public int reserved7; + public int reserved8; + } +#if never + + [StructLayout(LayoutKind.Sequential)] + public class SCROLLINFO { + public int cbSize = SizeOf(); + public int fMask; + public int nMin; + public int nMax; + public int nPage; + public int nPos; + public int nTrackPos; + + public SCROLLINFO() { + } + + public SCROLLINFO(int mask, int min, int max, int page, int pos) { + fMask = mask; + nMin = min; + nMax = max; + nPage = page; + nPos = pos; + } + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + private static int SizeOf() + { + return Marshal.SizeOf(typeof(SCROLLINFO)); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class TPMPARAMS { + public int cbSize = SizeOf(); + // rcExclude was a by-value RECT structure + public int rcExclude_left; + public int rcExclude_top; + public int rcExclude_right; + public int rcExclude_bottom; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(TPMPARAMS)); + } + } +#endif + +#if FRAMEWORK_NATIVEMETHODS || CORE_NATIVEMETHODS || BASE_NATIVEMETHODS || DRT_SEE_NATIVEMETHODS || UIAUTOMATIONTYPES + + [StructLayout(LayoutKind.Sequential)] + public class SIZE { + public int cx; + public int cy; + + public SIZE() + { + } + + public SIZE(int cx, int cy) { + this.cx = cx; + this.cy = cy; + } + + } + +#endif + + [StructLayout(LayoutKind.Sequential)] + public struct WINDOWPLACEMENT { + public int length; + public int flags; + public int showCmd; + // ptMinPosition was a by-value POINT structure + public int ptMinPosition_x; + public int ptMinPosition_y; + // ptMaxPosition was a by-value POINT structure + public int ptMaxPosition_x; + public int ptMaxPosition_y; + // rcNormalPosition was a by-value RECT structure + public int rcNormalPosition_left; + public int rcNormalPosition_top; + public int rcNormalPosition_right; + public int rcNormalPosition_bottom; + } +#if never + + [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)] + public class STARTUPINFO { + public int cb; + public string lpReserved; + public string lpDesktop; + public string lpTitle; + public int dwX; + public int dwY; + public int dwXSize; + public int dwYSize; + public int dwXCountChars; + public int dwYCountChars; + public int dwFillAttribute; + public int dwFlags; + public short wShowWindow; + public short cbReserved2; + public IntPtr lpReserved2; + public IntPtr hStdInput; + public IntPtr hStdOutput; + public IntPtr hStdError; + } + + [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)] + public class STARTUPINFO_I { + public int cb; + public IntPtr lpReserved; + public IntPtr lpDesktop; + public IntPtr lpTitle; + public int dwX; + public int dwY; + public int dwXSize; + public int dwYSize; + public int dwXCountChars; + public int dwYCountChars; + public int dwFillAttribute; + public int dwFlags; + public short wShowWindow; + public short cbReserved2; + public IntPtr lpReserved2; + public IntPtr hStdInput; + public IntPtr hStdOutput; + public IntPtr hStdError; + } + + [StructLayout(LayoutKind.Sequential)] + public class PAGESETUPDLG { + public int lStructSize; + public IntPtr hwndOwner; + public IntPtr hDevMode; + public IntPtr hDevNames; + public int Flags; + + //POINT ptPaperSize; + public int paperSizeX; + public int paperSizeY; + + // RECT rtMinMargin; + public int minMarginLeft; + public int minMarginTop; + public int minMarginRight; + public int minMarginBottom; + + // RECT rtMargin; + public int marginLeft; + public int marginTop; + public int marginRight; + public int marginBottom; + + public IntPtr hInstance; + public IntPtr lCustData; + public WndProc lpfnPageSetupHook; + public WndProc lpfnPagePaintHook; + public string lpPageSetupTemplateName; + public IntPtr hPageSetupTemplate; + } + + + + // x86 requires EXPLICIT packing of 1. + [StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Auto)] + public class PRINTDLG { + public int lStructSize; + + public IntPtr hwndOwner; + public IntPtr hDevMode; + public IntPtr hDevNames; + public IntPtr hDC; + + public int Flags; + + public short nFromPage; + public short nToPage; + public short nMinPage; + public short nMaxPage; + public short nCopies; + + public IntPtr hInstance; + public IntPtr lCustData; + + public WndProc lpfnPrintHook; + public WndProc lpfnSetupHook; + + public string lpPrintTemplateName; + public string lpSetupTemplateName; + + public IntPtr hPrintTemplate; + public IntPtr hSetupTemplate; + } + + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class PRINTDLGEX { + public int lStructSize; + + public IntPtr hwndOwner; + public IntPtr hDevMode; + public IntPtr hDevNames; + public IntPtr hDC; + + public int Flags; + public int Flags2; + + public int ExclusionFlags; + + public int nPageRanges; + public int nMaxPageRanges; + + public IntPtr pageRanges; + + public int nMinPage; + public int nMaxPage; + public int nCopies; + + public IntPtr hInstance; + public string lpPrintTemplateName; + + public WndProc lpCallback; + + public int nPropertyPages; + + public IntPtr lphPropertyPages; + + public int nStartPage; + public int dwResultAction; + + } + + // x86 requires EXPLICIT packing of 1. + [StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Auto)] + public class PRINTPAGERANGE { + public int nFromPage; + public int nToPage; + } + + + + [StructLayout(LayoutKind.Sequential)] + public class PICTDESC + { + internal int cbSizeOfStruct; + public int picType; + internal IntPtr union1; + internal int union2; + internal int union3; + + public static PICTDESC CreateBitmapPICTDESC(IntPtr hbitmap, IntPtr hpal) { + PICTDESC pictdesc = new PICTDESC(); + pictdesc.cbSizeOfStruct = 16; + pictdesc.picType = Ole.PICTYPE_BITMAP; + pictdesc.union1 = hbitmap; + pictdesc.union2 = (int)(((long)hpal) & 0xffffffff); + pictdesc.union3 = (int)(((long)hpal) >> 32); + return pictdesc; + } + + public static PICTDESC CreateIconPICTDESC(IntPtr hicon) { + PICTDESC pictdesc = new PICTDESC(); + pictdesc.cbSizeOfStruct = 12; + pictdesc.picType = Ole.PICTYPE_ICON; + pictdesc.union1 = hicon; + return pictdesc; + } + + public static PICTDESC CreateEnhMetafilePICTDESC(IntPtr hEMF) { + PICTDESC pictdesc = new PICTDESC(); + pictdesc.cbSizeOfStruct = 12; + pictdesc.picType = Ole.PICTYPE_ENHMETAFILE; + pictdesc.union1 = hEMF; + return pictdesc; + } + + public static PICTDESC CreateWinMetafilePICTDESC(IntPtr hmetafile, int x, int y) { + PICTDESC pictdesc = new PICTDESC(); + pictdesc.cbSizeOfStruct = 20; + pictdesc.picType = Ole.PICTYPE_METAFILE; + pictdesc.union1 = hmetafile; + pictdesc.union2 = x; + pictdesc.union3 = y; + return pictdesc; + } + + public virtual IntPtr GetHandle() { + return union1; + } + + public virtual IntPtr GetHPal() { + if (picType == Ole.PICTYPE_BITMAP) + return (IntPtr)((uint)union2 | (((long)union3) << 32)); + else + return IntPtr.Zero; + } + } + + [StructLayout(LayoutKind.Sequential)] + public sealed class tagFONTDESC { + public uint cbSizeofstruct = SizeOf(); + + [MarshalAs(UnmanagedType.LPWStr)] + public string lpstrName; + + [MarshalAs(UnmanagedType.I8)] + public long cySize; + + [MarshalAs(UnmanagedType.I2)] + public short sWeight; + + [MarshalAs(UnmanagedType.I2)] + public short sCharset; + + [MarshalAs(UnmanagedType.Bool)] + public bool fItalic; + + [MarshalAs(UnmanagedType.Bool)] + public bool fUnderline; + + [MarshalAs(UnmanagedType.Bool)] + public bool fStrikethrough; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(tagFONTDESC)); + } + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class MMCKINFO { + public int ckID; + public int cksize; + public int fccType; + public int dwDataOffset; + public int dwFlags; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class WAVEFORMATEX { + public System.Int16 wFormatTag; + public System.Int16 nChannels; + public int nSamplesPerSec; + public int nAvgBytesPerSec; + public System.Int16 nBlockAlign; + public System.Int16 wBitsPerSample; + public System.Int16 cbSize; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class CHOOSECOLOR { + public int lStructSize = SizeOf(); //ndirect.DllLib.sizeOf(this); + public IntPtr hwndOwner; + public IntPtr hInstance; + public int rgbResult; + public IntPtr lpCustColors; + public int Flags; + public IntPtr lCustData; + public WndProc lpfnHook; + public string lpTemplateName; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(CHOOSECOLOR)); + } + } + + //public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam); +#endif + + [StructLayout(LayoutKind.Sequential)] + public class BITMAP { + public int bmType = 0; + public int bmWidth = 0; + public int bmHeight = 0; + public int bmWidthBytes = 0; + public short bmPlanes = 0; + public short bmBitsPixel = 0; + public int bmBits = 0; + } + + +#if NEVER + [StructLayout(LayoutKind.Sequential)] + public class ICONINFO { + public int fIcon; + public int xHotspot; + public int yHotspot; + public IntPtr hbmMask; + public IntPtr hbmColor; + } + + + [StructLayout(LayoutKind.Sequential)] + public class DIBSECTION { + public BITMAP dsBm; + public BITMAPINFOHEADER dsBmih; + [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)] + public int[] dsBitfields; + public IntPtr dshSection; + public int dsOffset; + } + + [StructLayout(LayoutKind.Sequential)] + public class LOGPEN { + public int lopnStyle; + // lopnWidth was a by-value POINT structure + public int lopnWidth_x; + public int lopnWidth_y; + public int lopnColor; + } + + [StructLayout(LayoutKind.Sequential)] + public class LOGBRUSH { + public int lbStyle; + public int lbColor; + public IntPtr lbHatch; + } +#endif + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + public class LOGFONT { + public LOGFONT() { + } + public LOGFONT( LOGFONT lf ) + { + if (lf == null) + { + throw new ArgumentNullException("lf"); + } + + this.lfHeight = lf.lfHeight; + this.lfWidth = lf.lfWidth; + this.lfEscapement = lf.lfEscapement; + this.lfOrientation = lf.lfOrientation; + this.lfWeight = lf.lfWeight; + this.lfItalic = lf.lfItalic; + this.lfUnderline = lf.lfUnderline; + this.lfStrikeOut = lf.lfStrikeOut; + this.lfCharSet = lf.lfCharSet; + this.lfOutPrecision = lf.lfOutPrecision; + this.lfClipPrecision = lf.lfClipPrecision; + this.lfQuality = lf.lfQuality; + this.lfPitchAndFamily = lf.lfPitchAndFamily; + this.lfFaceName = lf.lfFaceName; + } + public int lfHeight; + public int lfWidth; + public int lfEscapement; + public int lfOrientation; + public int lfWeight; + public byte lfItalic; + public byte lfUnderline; + public byte lfStrikeOut; + public byte lfCharSet; + public byte lfOutPrecision; + public byte lfClipPrecision; + public byte lfQuality; + public byte lfPitchAndFamily; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] + public string lfFaceName; + } + +#if NEVER + [StructLayout(LayoutKind.Sequential)] + public class LOGPALETTE { + public short palVersion; + public short palNumEntries; + public int palPalEntry; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + public struct TEXTMETRIC + { + public int tmHeight; + public int tmAscent; + public int tmDescent; + public int tmInternalLeading; + public int tmExternalLeading; + public int tmAveCharWidth; + public int tmMaxCharWidth; + public int tmWeight; + public int tmOverhang; + public int tmDigitizedAspectX; + public int tmDigitizedAspectY; + public char tmFirstChar; + public char tmLastChar; + public char tmDefaultChar; + public char tmBreakChar; + public byte tmItalic; + public byte tmUnderlined; + public byte tmStruckOut; + public byte tmPitchAndFamily; + public byte tmCharSet; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] + public struct TEXTMETRICA + { + public int tmHeight; + public int tmAscent; + public int tmDescent; + public int tmInternalLeading; + public int tmExternalLeading; + public int tmAveCharWidth; + public int tmMaxCharWidth; + public int tmWeight; + public int tmOverhang; + public int tmDigitizedAspectX; + public int tmDigitizedAspectY; + public byte tmFirstChar; + public byte tmLastChar; + public byte tmDefaultChar; + public byte tmBreakChar; + public byte tmItalic; + public byte tmUnderlined; + public byte tmStruckOut; + public byte tmPitchAndFamily; + public byte tmCharSet; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class NOTIFYICONDATA { + public int cbSize = SizeOf(); + public IntPtr hWnd; + public int uID; + public int uFlags; + public int uCallbackMessage; + public IntPtr hIcon; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)] + public string szTip; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(NOTIFYICONDATA)); + } + } +#endif + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class MENUITEMINFO_T + { + public int cbSize = SizeOf(); + public int fMask = 0; + public int fType = 0; + public int fState = 0; + public int wID = 0; + public IntPtr hSubMenu = IntPtr.Zero; + public IntPtr hbmpChecked = IntPtr.Zero; + public IntPtr hbmpUnchecked = IntPtr.Zero; + public int dwItemData = 0; + public string dwTypeData = null; + public int cch = 0; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(MENUITEMINFO_T)); + } + } +#if never + + // This version allows you to read the string that's stuffed + // in the native menu item. You have to do the marshaling on + // your own though. + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class MENUITEMINFO_T_RW + { + public int cbSize = SizeOf(); + public int fMask; + public int fType; + public int fState; + public int wID; + public IntPtr hSubMenu; + public IntPtr hbmpChecked; + public IntPtr hbmpUnchecked; + public IntPtr dwItemData; + public IntPtr dwTypeData; + public int cch; + public IntPtr hbmpItem; // requires WINVER > 5 + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(MENUITEMINFO_T_RW)); + } + } + + + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + public struct MSAAMENUINFO + { + public int dwMSAASignature; + public int cchWText; + public string pszWText; + + public MSAAMENUINFO(string text) { + dwMSAASignature = unchecked((int) MSAA_MENU_SIG); + cchWText = text.Length; + pszWText = text; + } + } +#endif + + public delegate bool EnumThreadWindowsCallback(IntPtr hWnd, IntPtr lParam); + + [StructLayout(LayoutKind.Sequential)] + internal class OFNOTIFY + { + // hdr was a by-value NMHDR structure + internal IntPtr hdr_hwndFrom; + internal IntPtr hdr_idFrom; + internal int hdr_code; + + internal IntPtr lpOFN; + internal IntPtr pszFile; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + public class OPENFILENAME_I + { + public int lStructSize = SizeOf(); //ndirect.DllLib.sizeOf(this); + public IntPtr hwndOwner; + public IntPtr hInstance; + public string lpstrFilter; // use embedded nulls to separate filters + public IntPtr lpstrCustomFilter; + public int nMaxCustFilter; + public int nFilterIndex; + public IntPtr lpstrFile; + public int nMaxFile = NativeMethods.MAX_PATH; + public IntPtr lpstrFileTitle; + public int nMaxFileTitle = NativeMethods.MAX_PATH; + public string lpstrInitialDir; + public string lpstrTitle; + public int Flags; + public short nFileOffset; + public short nFileExtension; + public string lpstrDefExt; + public IntPtr lCustData; + public WndProc lpfnHook; + public string lpTemplateName; + public IntPtr pvReserved; + public int dwReserved; + public int FlagsEx; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(OPENFILENAME_I)); + } + } + + // constants related to the OPENFILENAME structure and file open/save dialogs + public const int CDN_FIRST = unchecked((int)(0U-601U)); + + public const int CDN_INITDONE = (CDN_FIRST - 0x0000); + public const int CDN_SELCHANGE = (CDN_FIRST - 0x0001); + public const int CDN_SHAREVIOLATION = (CDN_FIRST - 0x0003); + public const int CDN_FILEOK = (CDN_FIRST - 0x0005); + +#if !DRT && !UIAUTOMATIONTYPES + public const int CDM_FIRST = (int)WindowMessage.WM_USER + 100; + + public const int CDM_GETSPEC = (CDM_FIRST + 0x0000); + public const int CDM_GETFILEPATH = (CDM_FIRST + 0x0001); +#endif + + public const int DWL_MSGRESULT = 0; + + [StructLayout(LayoutKind.Sequential)] + public struct STYLESTRUCT { + public int styleOld; + public int styleNew; + } + +#if never + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto), CLSCompliantAttribute(false)] + public class CHOOSEFONT { + public int lStructSize = SizeOf(); // ndirect.DllLib.sizeOf(this); + public IntPtr hwndOwner; + public IntPtr hDC; + public IntPtr lpLogFont; + public int iPointSize; + public int Flags; + public int rgbColors; + public IntPtr lCustData; + public WndProc lpfnHook; + public string lpTemplateName; + public IntPtr hInstance; + public string lpszStyle; + public short nFontType; + public short ___MISSING_ALIGNMENT__; + public int nSizeMin; + public int nSizeMax; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(CHOOSEFONT)); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class BITMAPINFO { + // bmiHeader was a by-value BITMAPINFOHEADER structure + public int bmiHeader_biSize = 40; // ndirect.DllLib.sizeOf( BITMAPINFOHEADER.class ); + public int bmiHeader_biWidth; + public int bmiHeader_biHeight; + public short bmiHeader_biPlanes; + public short bmiHeader_biBitCount; + public int bmiHeader_biCompression; + public int bmiHeader_biSizeImage; + public int bmiHeader_biXPelsPerMeter; + public int bmiHeader_biYPelsPerMeter; + public int bmiHeader_biClrUsed; + public int bmiHeader_biClrImportant; + + // bmiColors was an embedded array of RGBQUAD structures + public byte bmiColors_rgbBlue; + public byte bmiColors_rgbGreen; + public byte bmiColors_rgbRed; + public byte bmiColors_rgbReserved; + } + + [StructLayout(LayoutKind.Sequential)] + public class BITMAPINFOHEADER { + public int biSize = 40; // ndirect.DllLib.sizeOf( this ); + public int biWidth = 0; + public int biHeight = 0; + public short biPlanes = 0; + public short biBitCount = 0; + public int biCompression = 0; + public int biSizeImage = 0; + public int biXPelsPerMeter = 0; + public int biYPelsPerMeter = 0; + public int biClrUsed = 0; + public int biClrImportant = 0; + } + + + public class Ole { + public const int PICTYPE_UNINITIALIZED = -1; + public const int PICTYPE_NONE = 0; + public const int PICTYPE_BITMAP = 1; + public const int PICTYPE_METAFILE = 2; + public const int PICTYPE_ICON = 3; + public const int PICTYPE_ENHMETAFILE = 4; + public const int STATFLAG_DEFAULT = 0; + public const int STATFLAG_NONAME = 1; + } + +#endif + [StructLayout(LayoutKind.Sequential)] + public class STATSTG + { + + [MarshalAs(UnmanagedType.LPWStr)] + public string pwcsName = null; + + public int type = 0; + [MarshalAs(UnmanagedType.I8)] + public long cbSize = 0; + [MarshalAs(UnmanagedType.I8)] + public long mtime = 0; + [MarshalAs(UnmanagedType.I8)] + public long ctime = 0; + [MarshalAs(UnmanagedType.I8)] + public long atime = 0; + [MarshalAs(UnmanagedType.I4)] + public int grfMode = 0; + [MarshalAs(UnmanagedType.I4)] + public int grfLocksSupported = 0; + + public int clsid_data1 = 0; + [MarshalAs(UnmanagedType.I2)] + public short clsid_data2 = 0; + [MarshalAs(UnmanagedType.I2)] + public short clsid_data3 = 0; + [MarshalAs(UnmanagedType.U1)] + public byte clsid_b0 = 0; + [MarshalAs(UnmanagedType.U1)] + public byte clsid_b1 = 0; + [MarshalAs(UnmanagedType.U1)] + public byte clsid_b2 = 0; + [MarshalAs(UnmanagedType.U1)] + public byte clsid_b3 = 0; + [MarshalAs(UnmanagedType.U1)] + public byte clsid_b4 = 0; + [MarshalAs(UnmanagedType.U1)] + public byte clsid_b5 = 0; + [MarshalAs(UnmanagedType.U1)] + public byte clsid_b6 = 0; + [MarshalAs(UnmanagedType.U1)] + public byte clsid_b7 = 0; + [MarshalAs(UnmanagedType.I4)] + public int grfStateBits = 0; + [MarshalAs(UnmanagedType.I4)] + public int reserved = 0; + } +#if never + + [StructLayout(LayoutKind.Sequential)] + public class FILETIME { + public int dwLowDateTime; + public int dwHighDateTime; + } + + [StructLayout(LayoutKind.Sequential)] + public class OVERLAPPED { + public int Internal; + public int InternalHigh; + public int Offset; + public int OffsetHigh; + public IntPtr hEvent; + } + + [StructLayout(LayoutKind.Sequential)] + public class SYSTEMTIME { + public short wYear; + public short wMonth; + public short wDayOfWeek; + public short wDay; + public short wHour; + public short wMinute; + public short wSecond; + public short wMilliseconds; + + public override string ToString() { + return "[SYSTEMTIME: " + + wDay.ToString() +"/" + wMonth.ToString() + "/" + wYear.ToString() + + " " + wHour.ToString() + ":" + wMinute.ToString() + ":" + wSecond.ToString() + + "]"; + } + } + + [ + StructLayout(LayoutKind.Sequential), + CLSCompliantAttribute(false) + ] + public sealed class _POINTL { + public int x; + public int y; + + } + + [StructLayout(LayoutKind.Sequential)] + public sealed class tagSIZE { + public int cx; + public int cy; + + } +#endif + + [Serializable] + [StructLayout(LayoutKind.Sequential)] + public class COMRECT { + public int left; + public int top; + public int right; + public int bottom; + + public COMRECT(int x, int y, int right, int bottom) + { + this.left = x; + this.top = y; + this.right = right; + this.bottom = bottom; + } + +// public COMRECT(System.Drawing.Rectangle r) { +// this.left = r.X; +// this.top = r.Y; +// this.right = r.Right; +// this.bottom = r.Bottom; +// } + + public COMRECT(RECT rect) { + this.left = rect.left; + this.top = rect.top; + this.bottom = rect.bottom; + this.right = rect.right; + } + + public void CopyTo(COMRECT destRect) { + destRect.left = left; + destRect.right = right; + destRect.top = top; + destRect.bottom = bottom; + } + + public bool IsEmpty { get { return left == right && top == bottom; } } + +// public RECT ToRECT() { +// return new RECT(left, top, right, bottom); +// } + + public override string ToString() { + return "Left = " + left + " Top " + top + " Right = " + right + " Bottom = " + bottom; + } + } + + [StructLayout(LayoutKind.Sequential)/*leftover(noAutoOffset)*/] + public sealed class tagOleMenuGroupWidths { + [MarshalAs(UnmanagedType.ByValArray, SizeConst=6)/*leftover(offset=0, widths)*/] + public int[] widths = new int[6]; + } + +#if never + [StructLayout(LayoutKind.Sequential)] + [Serializable] + public class MSOCRINFOSTRUCT { + public int cbSize = SizeOf(); // size of MSOCRINFO structure in bytes. + public int uIdleTimeInterval; // If olecrfNeedPeriodicIdleTime is registered + // in grfcrf, component needs to perform + // periodic idle time tasks during an idle phase + // every uIdleTimeInterval milliseconds. + public int grfcrf; // bit flags taken from olecrf values (above) + public int grfcadvf; // bit flags taken from olecadvf values (above) + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(MSOCRINFOSTRUCT)); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct NMLISTVIEW + { + public NMHDR hdr; + public int iItem; + public int iSubItem; + public int uNewState; + public int uOldState; + public int uChanged; + public IntPtr lParam; + } + + public class ConnectionPointCookie + { + private UnsafeNativeMethods.IConnectionPoint connectionPoint; + private int cookie; + private static bool connected; + #if DEBUG + private string callStack; + #endif + + /// + /// + /// Creates a connection point to of the given interface type. + /// which will call on a managed code sink that implements that interface. + /// + public ConnectionPointCookie(object source, object sink, Type eventInterface) : this(source, sink, eventInterface, true, out connected){ + } + + /// + /// + /// Creates a connection point to of the given interface type. + /// which will call on a managed code sink that implements that interface. + /// + public ConnectionPointCookie(object source, object sink, Type eventInterface, bool throwException, out bool connected){ + connected = false; + Exception ex = null; + if (source is UnsafeNativeMethods.IConnectionPointContainer) { + UnsafeNativeMethods.IConnectionPointContainer cpc = (UnsafeNativeMethods.IConnectionPointContainer)source; + + try { + Guid tmp = eventInterface.GUID; + if (cpc.FindConnectionPoint(ref tmp, out connectionPoint) != NativeMethods.S_OK) { + connectionPoint = null; + } + } + catch (Exception) { + connectionPoint = null; + } + + if (connectionPoint == null) { + ex = new ArgumentException(SR.GetString(SR.ConnPointSourceIF, eventInterface.Name )); + } + else if (sink == null || !eventInterface.IsInstanceOfType(sink)) { + ex = new InvalidCastException(SR.GetString(SR.ConnPointSinkIF)); + } + else { + int hr = connectionPoint.Advise(sink, ref cookie); + if (hr != S_OK) { + cookie = 0; + Marshal.ReleaseComObject(connectionPoint); + connectionPoint = null; + ex = new ExternalException(SR.GetString(SR.ConnPointAdviseFailed, eventInterface.Name, hr )); + } + else { + connected = true; + } + } + } + else { + ex = new InvalidCastException(SR.GetString(SR.ConnPointSourceIF, "IConnectionPointContainer")); + } + + + if (throwException && (connectionPoint == null || cookie == 0)) { + if (connectionPoint != null) { + Marshal.ReleaseComObject(connectionPoint); + } + + if (ex == null) { + throw new ArgumentException(SR.GetString(SR.ConnPointCouldNotCreate, eventInterface.Name )); + } + else { + throw ex; + } + } + + #if DEBUG + new EnvironmentPermission(PermissionState.Unrestricted).Assert(); + try { + callStack = Environment.StackTrace; + } + finally { + System.Security.CodeAccessPermission.RevertAssert(); + } + #endif + } + + /// + /// + /// Disconnect the current connection point. If the object is not connected, + /// this method will do nothing. + /// + public void Disconnect() { + Disconnect(false); + } + + /// + /// + /// Disconnect the current connection point. If the object is not connected, + /// this method will do nothing. + /// + public void Disconnect(bool release) { + if (connectionPoint != null && cookie != 0) { + connectionPoint.Unadvise(cookie); + cookie = 0; + + if (release) { + Marshal.ReleaseComObject(connectionPoint); + } + + connectionPoint = null; + } + } + + /// + /// + ~ConnectionPointCookie(){ + //System.Diagnostics.Debug.Assert(connectionPoint == null || cookie == 0, "We should never finalize an active connection point"); + //Disconnect(); + } + } +#endif + + [StructLayout(LayoutKind.Sequential)/*leftover(noAutoOffset)*/] + public sealed class POINTF + { + [MarshalAs(UnmanagedType.R4)/*leftover(offset=0, x)*/] + public float x; + + [MarshalAs(UnmanagedType.R4)/*leftover(offset=4, y)*/] + public float y; + + } + + [StructLayout(LayoutKind.Sequential)/*leftover(noAutoOffset)*/] + public sealed class OLEINPLACEFRAMEINFO + { + [MarshalAs(UnmanagedType.U4)/*leftover(offset=0, cb)*/] + public uint cb; + + public bool fMDIApp; + public IntPtr hwndFrame; + public IntPtr hAccel; + + [MarshalAs(UnmanagedType.U4)/*leftover(offset=16, cAccelEntries)*/] + public uint cAccelEntries; + + } + +#if never + [StructLayout(LayoutKind.Sequential)] + public struct NMLVDISPINFO_UNSAFE + { + // public NMHDR hdr; + public IntPtr hwndFrom; + public IntPtr idFrom; + public int code; + // public LVITEM item; + public int mask; + public int iItem; + public int iSubItem; + public int state; + public int stateMask; + public IntPtr pszText; + public int cchTextMax; + public int iImage; + public IntPtr lParam; + public int iIndent; + public int iGroupId; + public int cColumns; // tile view columns + public IntPtr puColumns; + } + + [StructLayout(LayoutKind.Sequential)] + public struct NMHDR + { + public IntPtr hwndFrom; + public IntPtr idFrom; //This is declared as UINT_PTR in winuser.h + public int code; + } + + /// + /// Critical : Elevates to UnmanagedCode permissions + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("376BD3AA-3845-101B-84ED-08002B2EC713"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPerPropertyBrowsing { + [PreserveSig] + int GetDisplayString( + int dispID, + [Out, MarshalAs(UnmanagedType.LPArray)] + string[] pBstr); + + [PreserveSig] + int MapPropertyToPage( + int dispID, + [Out] + out Guid pGuid); + + [PreserveSig] + int GetPredefinedStrings( + int dispID, + [Out] + CA_STRUCT pCaStringsOut, + [Out] + CA_STRUCT pCaCookiesOut); + + [PreserveSig] + int GetPredefinedValue( + int dispID, + [In, MarshalAs(UnmanagedType.U4)] + uint dwCookie, + [Out] + VARIANT pVarOut); + } + + /// + /// Critical : Elevates to UnmanagedCode permissions + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("4D07FC10-F931-11CE-B001-00AA006884E5"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface ICategorizeProperties { + + [PreserveSig] + int MapPropertyToCategory( + int dispID, + ref int categoryID); + + [PreserveSig] + int GetCategoryName( + int propcat, + [In, MarshalAs(UnmanagedType.U4)] + uint lcid, + out string categoryName); + } + + [StructLayout(LayoutKind.Sequential)/*leftover(noAutoOffset)*/] + public sealed class tagSIZEL + { + public int cx = 0; + public int cy = 0; + } +#endif + + [StructLayout(LayoutKind.Sequential)/*leftover(noAutoOffset)*/] + public sealed class tagOLEVERB + { + public int lVerb = 0; + + [MarshalAs(UnmanagedType.LPWStr)] // leftover(offset=4, customMarshal="UniStringMarshaller", lpszVerbName) + public string lpszVerbName = null; + + [MarshalAs(UnmanagedType.U4)] // leftover(offset=8, fuFlags) + public uint fuFlags = 0; + + [MarshalAs(UnmanagedType.U4)] // leftover(offset=12, grfAttribs) + public uint grfAttribs = 0; + } + + [StructLayout(LayoutKind.Sequential)/*leftover(noAutoOffset)*/] + public sealed class tagLOGPALETTE + { + [MarshalAs(UnmanagedType.U2)] // leftover(offset=0, palVersion) + public ushort palVersion = 0; + + [MarshalAs(UnmanagedType.U2)] // leftover(offset=2, palNumEntries) + public ushort palNumEntries = 0; + } + + [StructLayout(LayoutKind.Sequential)/*leftover(noAutoOffset)*/] + public sealed class tagCONTROLINFO + { + [MarshalAs(UnmanagedType.U4)/*leftover(offset=0, cb)*/] + public uint cb = (uint)SizeOf(); + + public IntPtr hAccel; + + [MarshalAs(UnmanagedType.U2)/*leftover(offset=8, cAccel)*/] + public ushort cAccel; + + [MarshalAs(UnmanagedType.U4)/*leftover(offset=10, dwFlags)*/] + public uint dwFlags; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(tagCONTROLINFO)); + } + } +#if never + [StructLayout(LayoutKind.Sequential)/*leftover(noAutoOffset)*/] + public sealed class CA_STRUCT + { + public int cElems; + public IntPtr pElems; + } +#endif + [StructLayout(LayoutKind.Sequential)] + public sealed class VARIANT { + [MarshalAs(UnmanagedType.I2)] + public short vt; + [MarshalAs(UnmanagedType.I2)] + public short reserved1; + [MarshalAs(UnmanagedType.I2)] + public short reserved2; + [MarshalAs(UnmanagedType.I2)] + public short reserved3; + + /// + /// Critical: This data is critical for set because it is used to make calls to Marshal.* + /// + public SecurityCriticalDataForSet data1; + + /// + /// Critical: This data is critical for set because it is used to make calls to Marshal.* + /// + public SecurityCriticalDataForSet data2; + + + public bool Byref{ + get{ + return 0 != (vt & (int)tagVT.VT_BYREF); + } + } + + /// + /// Critical: This calls into Marshal.Release which is link demand protected + /// TreatAsSafe: This is instance based and the internal pointer it is releasing is critical for set + /// + [SecurityCritical, SecurityTreatAsSafe] + public void Clear() { + if ((this.vt == (int)tagVT.VT_UNKNOWN || this.vt == (int)tagVT.VT_DISPATCH) && this.data1.Value != IntPtr.Zero) { + Marshal.Release(this.data1.Value); + } + + if (this.vt == (int)tagVT.VT_BSTR && this.data1.Value != IntPtr.Zero) { + SysFreeString(this.data1.Value); + } + + this.data1.Value = this.data2.Value = IntPtr.Zero; + this.vt = (int)tagVT.VT_EMPTY; + } + + ~VARIANT() { + Clear(); + } + + public void SuppressFinalize() + { + // Called if this VARIANT is returned to the caller in native world which is supposed to call + // VariantClear(). + // GC does not have to clear it. + GC.SuppressFinalize(this); + } + +#if never + public static VARIANT FromObject(Object var) { + VARIANT v = new VARIANT(); + + if (var == null) { + v.vt = (int)tagVT.VT_EMPTY; + } + else if (Convert.IsDBNull(var)) { + } + else { + Type t = var.GetType(); + + if (t == typeof(bool)) { + v.vt = (int)tagVT.VT_BOOL; + } + else if (t == typeof(byte)) { + v.vt = (int)tagVT.VT_UI1; + v.data1 = (IntPtr)Convert.ToByte(var); + } + else if (t == typeof(char)) { + v.vt = (int)tagVT.VT_UI2; + v.data1 = (IntPtr)Convert.ToChar(var); + } + else if (t == typeof(string)) { + v.vt = (int)tagVT.VT_BSTR; + v.data1 = SysAllocString(Convert.ToString(var)); + } + else if (t == typeof(short)) { + v.vt = (int)tagVT.VT_I2; + v.data1 = (IntPtr)Convert.ToInt16(var); + } + else if (t == typeof(int)) { + v.vt = (int)tagVT.VT_I4; + v.data1 = (IntPtr)Convert.ToInt32(var); + } + else if (t == typeof(long)) { + v.vt = (int)tagVT.VT_I8; + v.SetLong(Convert.ToInt64(var)); + } + else if (t == typeof(Decimal)) { + v.vt = (int)tagVT.VT_CY; + Decimal c = (Decimal)var; + // SBUrke, it's bizzare that we need to call this as a static! + v.SetLong(Decimal.ToInt64(c)); + } + else if (t == typeof(decimal)) { + v.vt = (int)tagVT.VT_DECIMAL; + Decimal d = Convert.ToDecimal(var); + v.SetLong(Decimal.ToInt64(d)); + } + else if (t == typeof(double)) { + v.vt = (int)tagVT.VT_R8; + // how do we handle double? + } + else if (t == typeof(float) || t == typeof(Single)) { + v.vt = (int)tagVT.VT_R4; + // how do we handle float? + } + else if (t == typeof(DateTime)) { + v.vt = (int)tagVT.VT_DATE; + v.SetLong(Convert.ToDateTime(var).ToFileTime()); + } + else if (t == typeof(SByte)) { + v.vt = (int)tagVT.VT_I1; + v.data1 = (IntPtr)Convert.ToSByte(var); + } + else if (t == typeof(UInt16)) { + v.vt = (int)tagVT.VT_UI2; + v.data1 = (IntPtr)Convert.ToUInt16(var); + } + else if (t == typeof(UInt32)) { + v.vt = (int)tagVT.VT_UI4; + v.data1 = (IntPtr)Convert.ToUInt32(var); + } + else if (t == typeof(UInt64)) { + v.vt = (int)tagVT.VT_UI8; + v.SetLong((long)Convert.ToUInt64(var)); + } + else if (t == typeof(object) || t == typeof(UnsafeNativeMethods.IDispatch) || t.IsCOMObject) { + v.vt = (t == typeof(UnsafeNativeMethods.IDispatch) ? (short)tagVT.VT_DISPATCH : (short)tagVT.VT_UNKNOWN); + v.data1 = Marshal.GetIUnknownForObject(var); + } + else { + Invariant.Assert(false, "Unsupported object type!"); + } + } + return v; + } +#endif + + [DllImport(ExternDll.Oleaut32,CharSet=CharSet.Auto)] + private static extern IntPtr SysAllocString([In, MarshalAs(UnmanagedType.LPWStr)]string s); + + [DllImport(ExternDll.Oleaut32,CharSet=CharSet.Auto)] + private static extern void SysFreeString(IntPtr pbstr); + /// + /// Critical: Sets the pointer to an arbitrary long + /// + [SecurityCritical] + public void SetLong(long lVal) { + data1.Value = (IntPtr)(lVal & 0xFFFFFFFF); + data2.Value = (IntPtr)((lVal >> 32) & 0xFFFFFFFF); + } + + /// + /// Critical: Calls Marshal.AllocCoTaskMem, .WriteInt16 and .WriteInt32 which have LinkDemands. + /// Writes to unmanaged memory and returns a pointer to it. + /// + [SecurityCritical] + public IntPtr ToCoTaskMemPtr() { + IntPtr mem = Marshal.AllocCoTaskMem(16); + Marshal.WriteInt16(mem, vt); + Marshal.WriteInt16(mem, 2, reserved1); + Marshal.WriteInt16(mem, 4, reserved2); + Marshal.WriteInt16(mem, 6, reserved3); + Marshal.WriteInt32(mem, 8, (int) data1.Value); + Marshal.WriteInt32(mem, 12, (int) data2.Value); + return mem; + } + + /// + /// Critical: Converts an intptr to an object , it acceses PtrToStruct which is critical + /// + [SecurityCritical] + public object ToObject() { + IntPtr val = data1.Value; + long longVal; + + int vtType = (int)(this.vt & (short)tagVT.VT_TYPEMASK); + + switch (vtType) { + case (int)tagVT.VT_EMPTY: + return null; + case (int)tagVT.VT_NULL: + return Convert.DBNull; + + case (int)tagVT.VT_I1: + if (Byref) { + val = (IntPtr) Marshal.ReadByte(val); + } + return (SByte) (0xFF & (SByte) val); + + case (int)tagVT.VT_UI1: + if (Byref) { + val = (IntPtr) Marshal.ReadByte(val); + } + + return (byte) (0xFF & (byte) val); + + case (int)tagVT.VT_I2: + if (Byref) { + val = (IntPtr) Marshal.ReadInt16(val); + } + return (short)(0xFFFF & (short) val); + + case (int)tagVT.VT_UI2: + if (Byref) { + val = (IntPtr) Marshal.ReadInt16(val); + } + return (UInt16)(0xFFFF & (UInt16) val); + + case (int)tagVT.VT_I4: + case (int)tagVT.VT_INT: + if (Byref) { + val = (IntPtr) Marshal.ReadInt32(val); + } + return (int)val; + + case (int)tagVT.VT_UI4: + case (int)tagVT.VT_UINT: + if (Byref) { + val = (IntPtr) Marshal.ReadInt32(val); + } + return (UInt32)val; + + case (int)tagVT.VT_I8: + case (int)tagVT.VT_UI8: + if (Byref) { + longVal = Marshal.ReadInt64(val); + } + else { + longVal = ((uint)data1.Value & 0xffffffff) | ((uint)data2.Value << 32); + } + + if (vt == (int)tagVT.VT_I8) { + return (long)longVal; + } + else { + return (UInt64)longVal; + } + } + + if (Byref) { + val = GetRefInt(val); + } + + switch (vtType) { + case (int)tagVT.VT_R4: + case (int)tagVT.VT_R8: + + // can I use unsafe here? + throw new FormatException(/*SR.GetString(SR.CannotConvertIntToFloat)*/); + + case (int)tagVT.VT_CY: + // internally currency is 8-byte int scaled by 10,000 + longVal = ((uint)data1.Value & 0xffffffff) | ((uint)data2.Value << 32); + return new Decimal(longVal); + case (int)tagVT.VT_DATE: + throw new FormatException(/*SR.GetString(SR.CannotConvertDoubleToDate)*/); + + case (int)tagVT.VT_BSTR: + case (int)tagVT.VT_LPWSTR: + return Marshal.PtrToStringUni(val); + + case (int)tagVT.VT_LPSTR: + return Marshal.PtrToStringAnsi(val); + + case (int)tagVT.VT_DISPATCH: + case (int)tagVT.VT_UNKNOWN: + { + return Marshal.GetObjectForIUnknown(val); + } + + case (int)tagVT.VT_HRESULT: + return val; + + case (int)tagVT.VT_DECIMAL: + longVal = ((uint)data1.Value & 0xffffffff) | ((uint)data2.Value << 32); + return new Decimal(longVal); + + case (int)tagVT.VT_BOOL: + return (val != IntPtr.Zero); + + case (int)tagVT.VT_VARIANT: + VARIANT varStruct = (VARIANT)UnsafeNativeMethods.PtrToStructure(val, typeof(VARIANT)); + return varStruct.ToObject(); + case (int)tagVT.VT_CLSID: + //Debug.Fail("PtrToStructure will not work with System.Guid..."); + Guid guid =(Guid)UnsafeNativeMethods.PtrToStructure(val, typeof(Guid)); + return guid; + + case (int)tagVT.VT_FILETIME: + longVal = ((uint)data1.Value & 0xffffffff) | ((uint)data2.Value << 32); + return new DateTime(longVal); + + case (int)tagVT.VT_ARRAY: + //gSAFEARRAY sa = (tagSAFEARRAY)Marshal.PtrToStructure(val), typeof(tagSAFEARRAY)); + //return GetArrayFromSafeArray(sa); + + case (int)tagVT.VT_USERDEFINED: + case (int)tagVT.VT_VOID: + case (int)tagVT.VT_PTR: + case (int)tagVT.VT_SAFEARRAY: + case (int)tagVT.VT_CARRAY: + + case (int)tagVT.VT_RECORD: + case (int)tagVT.VT_BLOB: + case (int)tagVT.VT_STREAM: + case (int)tagVT.VT_STORAGE: + case (int)tagVT.VT_STREAMED_OBJECT: + case (int)tagVT.VT_STORED_OBJECT: + case (int)tagVT.VT_BLOB_OBJECT: + case (int)tagVT.VT_CF: + case (int)tagVT.VT_BSTR_BLOB: + case (int)tagVT.VT_VECTOR: + case (int)tagVT.VT_BYREF: + //case (int)tagVT.VT_RESERVED: + default: + return null; + } + } + /// + /// Critical: Reads an arbitrary IntPtr + /// + [SecurityCritical] + private static IntPtr GetRefInt(IntPtr value) { + return Marshal.ReadIntPtr(value); + } + } + +#if never + [StructLayout(LayoutKind.Sequential)/*leftover(noAutoOffset)*/] + public sealed class tagLICINFO + { + [MarshalAs(UnmanagedType.U4)/*leftover(offset=0, cb)*/] + public int cbLicInfo = SizeOf(); + + public int fRuntimeAvailable; + public int fLicVerified; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(tagLICINFO)); + } + } +#endif + + public enum tagVT { + VT_EMPTY = 0, + VT_NULL = 1, + VT_I2 = 2, + VT_I4 = 3, + VT_R4 = 4, + VT_R8 = 5, + VT_CY = 6, + VT_DATE = 7, + VT_BSTR = 8, + VT_DISPATCH = 9, + VT_ERROR = 10, + VT_BOOL = 11, + VT_VARIANT = 12, + VT_UNKNOWN = 13, + VT_DECIMAL = 14, + VT_I1 = 16, + VT_UI1 = 17, + VT_UI2 = 18, + VT_UI4 = 19, + VT_I8 = 20, + VT_UI8 = 21, + VT_INT = 22, + VT_UINT = 23, + VT_VOID = 24, + VT_HRESULT = 25, + VT_PTR = 26, + VT_SAFEARRAY = 27, + VT_CARRAY = 28, + VT_USERDEFINED = 29, + VT_LPSTR = 30, + VT_LPWSTR = 31, + VT_RECORD = 36, + VT_FILETIME = 64, + VT_BLOB = 65, + VT_STREAM = 66, + VT_STORAGE = 67, + VT_STREAMED_OBJECT = 68, + VT_STORED_OBJECT = 69, + VT_BLOB_OBJECT = 70, + VT_CF = 71, + VT_CLSID = 72, + VT_BSTR_BLOB = 4095, + VT_VECTOR = 4096, + VT_ARRAY = 8192, + VT_BYREF = 16384, + VT_RESERVED = 32768, + VT_ILLEGAL = 65535, + VT_ILLEGALMASKED = 4095, + VT_TYPEMASK = 4095 + } + + public delegate void TimerProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); +#if never + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class WNDCLASS_D { + public int style; + public WndProc lpfnWndProc; + public int cbClsExtra = 0; + public int cbWndExtra = 0; + public IntPtr hInstance = IntPtr.Zero; + public IntPtr hIcon = IntPtr.Zero; + public IntPtr hCursor = IntPtr.Zero; + public IntPtr hbrBackground = IntPtr.Zero; + public string lpszMenuName = null; + public string lpszClassName = null; + } + + public class MSOCM { + // MSO Component registration flags + public const int msocrfNeedIdleTime = 1; + public const int msocrfNeedPeriodicIdleTime = 2; + public const int msocrfPreTranslateKeys = 4; + public const int msocrfPreTranslateAll = 8; + public const int msocrfNeedSpecActiveNotifs = 16; + public const int msocrfNeedAllActiveNotifs = 32; + public const int msocrfExclusiveBorderSpace = 64; + public const int msocrfExclusiveActivation = 128; + public const int msocrfNeedAllMacEvents = 256; + public const int msocrfMaster = 512; + + // MSO Component registration advise flags (see msocstate enumeration) + public const int msocadvfModal = 1; + public const int msocadvfRedrawOff = 2; + public const int msocadvfWarningsOff = 4; + public const int msocadvfRecording = 8; + + // MSO Component Host flags + public const int msochostfExclusiveBorderSpace = 1; + + // MSO idle flags, passed to IMsoComponent::FDoIdle and + // IMsoStdComponentMgr::FDoIdle. + public const int msoidlefPeriodic = 1; + public const int msoidlefNonPeriodic = 2; + public const int msoidlefPriority = 4; + public const int msoidlefAll = -1; + + // MSO Reasons for pushing a message loop, passed to + // IMsoComponentManager::FPushMessageLoop and + // IMsoComponentHost::FPushMessageLoop. The host should remain in message + // loop until IMsoComponent::FContinueMessageLoop + public const int msoloopMain = -1; // Note this is not an official MSO loop -- it just must be distinct. + public const int msoloopFocusWait = 1; + public const int msoloopDoEvents = 2; + public const int msoloopDebug = 3; + public const int msoloopModalForm = 4; + public const int msoloopModalAlert = 5; + + + /* msocstate values: state IDs passed to + IMsoComponent::OnEnterState, + IMsoComponentManager::OnComponentEnterState/FOnComponentExitState/FInState, + IMsoComponentHost::OnComponentEnterState, + IMsoStdComponentMgr::OnHostEnterState/FOnHostExitState/FInState. + When the host or a component is notified through one of these methods that + another entity (component or host) is entering or exiting a state + identified by one of these state IDs, the host/component should take + appropriate action: + msocstateModal (modal state): + If app is entering modal state, host/component should disable + its toplevel windows, and reenable them when app exits this + state. Also, when this state is entered or exited, host/component + should notify approprate inplace objects via + IOleInPlaceActiveObject::EnableModeless. + msocstateRedrawOff (redrawOff state): + If app is entering redrawOff state, host/component should disable + repainting of its windows, and reenable repainting when app exits + this state. + msocstateWarningsOff (warningsOff state): + If app is entering warningsOff state, host/component should disable + the presentation of any user warnings, and reenable this when + app exits this state. + msocstateRecording (Recording state): + Used to notify host/component when Recording is turned on or off. */ + public const int msocstateModal = 1; + public const int msocstateRedrawOff = 2; + public const int msocstateWarningsOff = 3; + public const int msocstateRecording = 4; + + + /* ** Comments on State Contexts ** + IMsoComponentManager::FCreateSubComponentManager allows one to create a + hierarchical tree of component managers. This tree is used to maintain + multiple contexts with regard to msocstateXXX states. These contexts are + referred to as 'state contexts'. + Each component manager in the tree defines a state context. The + components registered with a particular component manager or any of its + descendents live within that component manager's state context. Calls + to IMsoComponentManager::OnComponentEnterState/FOnComponentExitState + can be used to affect all components, only components within the component + manager's state context, or only those components that are outside of the + component manager's state context. IMsoComponentManager::FInState is used + to query the state of the component manager's state context at its root. + + msoccontext values: context indicators passed to + IMsoComponentManager::OnComponentEnterState/FOnComponentExitState. + These values indicate the state context that is to be affected by the + state change. + In IMsoComponentManager::OnComponentEnterState/FOnComponentExitState, + the comp mgr informs only those components/host that are within the + specified state context. */ + public const int msoccontextAll = 0; + public const int msoccontextMine = 1; + public const int msoccontextOthers = 2; + + /* ** WM_MOUSEACTIVATE Note (for top level compoenents and host) ** + If the active (or tracking) comp's reg info indicates that it + wants mouse messages, then no MA_xxxANDEAT value should be returned + from WM_MOUSEACTIVATE, so that the active (or tracking) comp will be able + to process the resulting mouse message. If one does not want to examine + the reg info, no MA_xxxANDEAT value should be returned from + WM_MOUSEACTIVATE if any comp is active (or tracking). + One can query the reg info of the active (or tracking) component at any + time via IMsoComponentManager::FGetActiveComponent. */ + + /* msogac values: values passed to + IMsoComponentManager::FGetActiveComponent. */ + public const int msogacActive = 0; + public const int msogacTracking = 1; + public const int msogacTrackingOrActive = 2; + + /* msocWindow values: values passed to IMsoComponent::HwndGetWindow. */ + public const int msocWindowFrameToplevel = 0; + public const int msocWindowFrameOwner = 1; + public const int msocWindowComponent = 2; + public const int msocWindowDlgOwner = 3; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class TOOLINFO_T + { + public int cbSize = SizeOf(); + public int uFlags; + public IntPtr hwnd; + public IntPtr uId; + public RECT rect; + public IntPtr hinst; + public string lpszText; + public IntPtr lParam; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(TOOLINFO_T)); + } + } + + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class TOOLINFO_TOOLTIP + { + public int cbSize = SizeOf(); + public int uFlags; + public IntPtr hwnd; + public IntPtr uId; + public RECT rect; + public IntPtr hinst; + public IntPtr lpszText; + public IntPtr lParam; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(TOOLINFO_TOOLTIP)); + } + } + + + [StructLayout(LayoutKind.Sequential)] + public sealed class tagDVTARGETDEVICE { + [MarshalAs(UnmanagedType.U4)] + public uint tdSize; + [MarshalAs(UnmanagedType.U2)] + public ushort tdDriverNameOffset; + [MarshalAs(UnmanagedType.U2)] + public ushort tdDeviceNameOffset; + [MarshalAs(UnmanagedType.U2)] + public ushort tdPortNameOffset; + [MarshalAs(UnmanagedType.U2)] + public ushort tdExtDevmodeOffset; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public struct TV_ITEM { + public int mask; + public IntPtr hItem; + public int state; + public int stateMask; + public IntPtr /* LPTSTR */ pszText; + public int cchTextMax; + public int iImage; + public int iSelectedImage; + public int cChildren; + public IntPtr lParam; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public struct TVSORTCB { + public IntPtr hParent; + public NativeMethods.TreeViewCompareCallback lpfnCompare; + public IntPtr lParam; + } + + + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public struct TV_INSERTSTRUCT { + public IntPtr hParent; + public IntPtr hInsertAfter; + public int item_mask; + public IntPtr item_hItem; + public int item_state; + public int item_stateMask; + public IntPtr /* LPTSTR */ item_pszText; + public int item_cchTextMax; + public int item_iImage; + public int item_iSelectedImage; + public int item_cChildren; + public IntPtr item_lParam; + public int item_iIntegral; + } + + [StructLayout(LayoutKind.Sequential)] + public struct NMTREEVIEW + { + public NMHDR nmhdr; + public int action; + public TV_ITEM itemOld; + public TV_ITEM itemNew; + public int ptDrag_X; // This should be declared as POINT + public int ptDrag_Y; // we use unsafe blocks to manipulate + // NMTREEVIEW quickly, and POINT is declared + // as a class. Too much churn to change POINT + // now. + } + + [StructLayout(LayoutKind.Sequential)] + public struct NMTVGETINFOTIP + { + public NMHDR nmhdr; + public string pszText; + public int cchTextMax; + public IntPtr item; + public IntPtr lParam; + + } + + [StructLayout(LayoutKind.Sequential)] + public class NMTVDISPINFO + { + public NMHDR hdr; + public TV_ITEM item; + } + + [StructLayout(LayoutKind.Sequential)] + public sealed class POINTL { + public int x; + public int y; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public struct HIGHCONTRAST { + public int cbSize; + public int dwFlags; + public string lpszDefaultScheme; + } +#endif + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public struct HIGHCONTRAST_I { + public int cbSize; + public int dwFlags; + public IntPtr lpszDefaultScheme; + } +#if never + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class TCITEM_T + { + public int mask; + public int dwState; + public int dwStateMask; + public string pszText; + public int cchTextMax; + public int iImage; + public IntPtr lParam; + } +#endif + + [StructLayout(LayoutKind.Sequential)/*leftover(noAutoOffset)*/] + public sealed class DISPPARAMS + { + public IntPtr rgvarg; + public IntPtr rgdispidNamedArgs; + [MarshalAs(UnmanagedType.U4)/*leftover(offset=8, cArgs)*/] + public uint cArgs; + [MarshalAs(UnmanagedType.U4)/*leftover(offset=12, cNamedArgs)*/] + public uint cNamedArgs; + } + +#if never + public enum tagINVOKEKIND { + INVOKE_FUNC = 1, + INVOKE_PROPERTYGET = 2, + INVOKE_PROPERTYPUT = 4, + INVOKE_PROPERTYPUTREF = 8 + } +#endif + + [StructLayout(LayoutKind.Sequential)] + public class EXCEPINFO { + [MarshalAs(UnmanagedType.U2)] + public ushort wCode; + [MarshalAs(UnmanagedType.U2)] + public ushort wReserved; + [MarshalAs(UnmanagedType.BStr)] + public string bstrSource; + [MarshalAs(UnmanagedType.BStr)] + public string bstrDescription; + [MarshalAs(UnmanagedType.BStr)] + public string bstrHelpFile; + [MarshalAs(UnmanagedType.U4)] + public uint dwHelpContext; + + public IntPtr pvReserved; + + public IntPtr pfnDeferredFillIn; + [MarshalAs(UnmanagedType.I4)] + public int scode; + } + +#if never + public enum tagDESCKIND { + DESCKIND_NONE = 0, + DESCKIND_FUNCDESC = 1, + DESCKIND_VARDESC = 2, + DESCKIND_TYPECOMP = 3, + DESCKIND_IMPLICITAPPOBJ = 4, + DESCKIND_MAX = 5 + } + + [StructLayout(LayoutKind.Sequential)] + public sealed class tagFUNCDESC { + public int memid; + [MarshalAs(UnmanagedType.U2)] + public short lprgscode; + + // This is marked as NATIVE_TYPE_PTR, + // but the EE doesn't look for that, tries to handle it as + // a ELEMENT_TYPE_VALUECLASS and fails because it + // isn't a NATIVE_TYPE_NESTEDSTRUCT + /*[MarshalAs(UnmanagedType.PTR)]*/ + + public /*NativeMethods.tagELEMDESC*/ IntPtr lprgelemdescParam; + + // cpb, SBurke, the EE chokes on Enums in structs + + public /*NativeMethods.tagFUNCKIND*/ int funckind; + + public /*NativeMethods.tagINVOKEKIND*/ int invkind; + + public /*NativeMethods.tagCALLCONV*/ int callconv; + [MarshalAs(UnmanagedType.I2)] + public short cParams; + [MarshalAs(UnmanagedType.I2)] + public short cParamsOpt; + [MarshalAs(UnmanagedType.I2)] + public short oVft; + [MarshalAs(UnmanagedType.I2)] + public short cScodes; + public NativeMethods.value_tagELEMDESC elemdescFunc; + [MarshalAs(UnmanagedType.U2)] + public ushort wFuncFlags; + } + + [StructLayout(LayoutKind.Sequential)] + public sealed class tagVARDESC { + public int memid; + public IntPtr lpstrSchema; + public IntPtr unionMember; + public NativeMethods.value_tagELEMDESC elemdescVar; + [MarshalAs(UnmanagedType.U2)] + public ushort wVarFlags; + public /*NativeMethods.tagVARKIND*/ int varkind; + } + + [StructLayout(LayoutKind.Sequential)] + public struct value_tagELEMDESC { + public NativeMethods.tagTYPEDESC tdesc; + public NativeMethods.tagPARAMDESC paramdesc; + } + +#endif + [StructLayout(LayoutKind.Sequential)] + public struct WINDOWPOS { + public IntPtr hwnd; + public IntPtr hwndInsertAfter; + public int x; + public int y; + public int cx; + public int cy; + public int flags; + } +#if never + + [StructLayout(LayoutKind.Sequential)] + public class DRAWITEMSTRUCT { + public int CtlType; + public int CtlID; + public int itemID; + public int itemAction; + public int itemState; + public IntPtr hwndItem; + public IntPtr hDC; + public RECT rcItem; + public IntPtr itemData; + } + + [StructLayout(LayoutKind.Sequential)] + public class MEASUREITEMSTRUCT { + public int CtlType; + public int CtlID; + public int itemID; + public int itemWidth; + public int itemHeight; + public IntPtr itemData; + } + + [StructLayout(LayoutKind.Sequential)] + public class HELPINFO { + public int cbSize = SizeOf(); + public int iContextType; + public int iCtrlId; + public IntPtr hItemHandle; + public int dwContextId; + public POINT MousePos; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(HELPINFO)); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class ACCEL { + public byte fVirt; + public short key; + public short cmd; + } +#endif + + [StructLayout(LayoutKind.Sequential)] + public class MINMAXINFO { + public POINT ptReserved = new POINT(); + public POINT ptMaxSize = new POINT(); + public POINT ptMaxPosition = new POINT(); + public POINT ptMinTrackSize = new POINT(); + public POINT ptMaxTrackSize = new POINT(); + } +#if never + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class CREATESTRUCT { + public IntPtr lpCreateParams = IntPtr.Zero; + public IntPtr hInstance = IntPtr.Zero; + public IntPtr hMenu = IntPtr.Zero; + public IntPtr hwndParent = IntPtr.Zero; + public int cy = 0; + public int cx = 0; + public int y = 0; + public int x = 0; + public int style = 0; + public string lpszName = null; + public string lpszClass = null; + public int dwExStyle = 0; + } +#endif + +#if never + [ComImport(), Guid("B196B28B-BAB4-101A-B69C-00AA00341D07"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface ISpecifyPropertyPages { + void GetPages( + [Out] + NativeMethods.tagCAUUID pPages); + + } + + [StructLayout(LayoutKind.Sequential)/*leftover(noAutoOffset)*/] + public sealed class tagCAUUID + { + [MarshalAs(UnmanagedType.U4)/*leftover(offset=0, cElems)*/] + public uint cElems; + public IntPtr pElems; + } + + [StructLayout(LayoutKind.Sequential)] + public struct NMTOOLBAR + { + public NMHDR hdr; + public int iItem; + public TBBUTTON tbButton; + public int cchText; + public IntPtr pszText; + } + + [StructLayout(LayoutKind.Sequential)] + public struct TBBUTTON { + public int iBitmap; + public int idCommand; + public byte fsState; + public byte fsStyle; + public byte bReserved0; + public byte bReserved1; + public IntPtr dwData; + public IntPtr iString; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class TOOLTIPTEXT + { + public NMHDR hdr; + public IntPtr lpszText; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst=80)] + public string szText; + + public IntPtr hinst; + public int uFlags; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] + public class TOOLTIPTEXTA + { + public NMHDR hdr; + public IntPtr lpszText; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst=80)] + public string szText; + + public IntPtr hinst; + public int uFlags; + } + + [StructLayout(LayoutKind.Sequential)] + public struct NMTBHOTITEM + { + public NMHDR hdr; + public int idOld; + public int idNew; + public int dwFlags; + } + + public const int HICF_OTHER = 0x00000000; + public const int HICF_MOUSE = 0x00000001; // Triggered by mouse + public const int HICF_ARROWKEYS = 0x00000002; // Triggered by arrow keys + public const int HICF_ACCELERATOR = 0x00000004; // Triggered by accelerator + public const int HICF_DUPACCEL = 0x00000008; // This accelerator is not unique + public const int HICF_ENTERING = 0x00000010; // idOld is invalid + public const int HICF_LEAVING = 0x00000020; // idNew is invalid + public const int HICF_RESELECT = 0x00000040; // hot item reselected + public const int HICF_LMOUSE = 0x00000080; // left mouse button selected + public const int HICF_TOGGLEDROPDOWN = 0x00000100; // Toggle button's dropdown state + + + [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)] + public class HDITEM + { + public int mask; + public int cxy; + public string pszText; + public IntPtr hbm; + public int cchTextMax; + public int fmt; + public IntPtr lParam; + public int iImage; + public int iOrder; + public int type; + public IntPtr pvFilter; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public struct TOOLINFO + { + public int cbSize; + public int uFlags; + public IntPtr hwnd; + public IntPtr uId; + public RECT rect; + public IntPtr hinst; + public string lpszText; + public IntPtr lParam; + } + + [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)] + public struct TBBUTTONINFO + { + public int cbSize; + public int dwMask; + public int idCommand; + public int iImage; + public byte fsState; + public byte fsStyle; + public short cx; + public IntPtr lParam; + public IntPtr pszText; + public int cchTest; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class TV_HITTESTINFO { + public int pt_x; + public int pt_y; + public int flags; + public IntPtr hItem; + } + + [StructLayout(LayoutKind.Sequential)] + public class NMTVCUSTOMDRAW + { + public NMCUSTOMDRAW nmcd; + public int clrText; + public int clrTextBk; + public int iLevel; + } + + [StructLayout(LayoutKind.Sequential)] + public struct NMCUSTOMDRAW { + public NMHDR nmcd; + public int dwDrawStage; + public IntPtr hdc; + public RECT rc; + public IntPtr dwItemSpec; + public int uItemState; + public IntPtr lItemlParam; + } + + [StructLayout(LayoutKind.Sequential)] + public class NMTTCUSTOMDRAW + { + public NMCUSTOMDRAW nmcd; + public int uDrawFlags; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class MCHITTESTINFO { + public int cbSize = SizeOf(); + public int pt_x; + public int pt_y; + public int uHit; + public short st_wYear; + public short st_wMonth; + public short st_wDayOfWeek; + public short st_wDay; + public short st_wHour; + public short st_wMinute; + public short st_wSecond; + public short st_wMilliseconds; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(MCHITTESTINFO)); + } + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class NMSELCHANGE + { + public NMHDR nmhdr; + public SYSTEMTIME stSelStart; + public SYSTEMTIME stSelEnd; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class NMDAYSTATE + { + public NMHDR nmhdr; + public SYSTEMTIME stStart; + public int cDayState; + public IntPtr prgDayState; + } + + [StructLayout(LayoutKind.Sequential)] + public struct NMLVCUSTOMDRAW + { + public NMCUSTOMDRAW nmcd; + public int clrText; + public int clrTextBk; + public int iSubItem; + public int dwItemType; + // Item Custom Draw + public int clrFace; + public int iIconEffect; + public int iIconPhase; + public int iPartId; + public int iStateId; + // Group Custom Draw + public RECT rcText; + public uint uAlign; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class NMLVGETINFOTIP + { + public NMHDR nmhdr; + public int flags; + public IntPtr lpszText; + public int cchTextMax; + public int item; + public int subItem; + public IntPtr lParam; + } + + [StructLayout(LayoutKind.Sequential)] + public class NMLVKEYDOWN + { + public NMHDR hdr; + public short wVKey; + public uint flags; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class LVHITTESTINFO { + public int pt_x; + public int pt_y; + public int flags; + public int iItem; + public int iSubItem; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class LVBKIMAGE + { + public int ulFlags; + public IntPtr hBmp; // not used + public string pszImage; + public int cchImageMax; + public int xOffset; + public int yOffset; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class LVCOLUMN_T + { + public int mask; + public int fmt; + public int cx; + public string pszText; + public int cchTextMax; + public int iSubItem; + public int iImage; + public int iOrder; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public struct LVFINDINFO { + public int flags; + public string psz; + public IntPtr lParam; + public int ptX; // was POINT pt + public int ptY; + public int vkDirection; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public struct LVITEM { + public int mask; + public int iItem; + public int iSubItem; + public int state; + public int stateMask; + public string pszText; + public int cchTextMax; + public int iImage; + public IntPtr lParam; + public int iIndent; + public int iGroupId; + public int cColumns; // tile view columns + public IntPtr puColumns; + + public unsafe void Reset() { + pszText = null; + mask = 0; + iItem = 0; + iSubItem = 0; + stateMask = 0; + state = 0; + cchTextMax = 0; + iImage = 0; + lParam = IntPtr.Zero; + iIndent = 0; + iGroupId = 0; + cColumns = 0; + puColumns = IntPtr.Zero; + } + + public override string ToString() { + return "LVITEM: pszText = " + pszText + + ", iItem = " + iItem.ToString() + + ", iSubItem = " + iSubItem.ToString() + + ", state = " + state.ToString() + + ", iGroupId = " + iGroupId.ToString() + + ", cColumns = " + cColumns.ToString(); + } + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public struct LVITEM_NOTEXT { + public int mask; + public int iItem; + public int iSubItem; + public int state; + public int stateMask; + public IntPtr /*string*/ pszText; + public int cchTextMax; + public int iImage; + public IntPtr lParam; + public int iIndent; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class LVCOLUMN { + public int mask; + public int fmt; + public int cx; + public IntPtr /* LPWSTR */ pszText; + public int cchTextMax; + public int iSubItem; + public int iImage; + public int iOrder; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + public class LVGROUP { + public uint cbSize = (uint)SizeOf(); + public uint mask; + public IntPtr pszHeader; + public int cchHeader; + public IntPtr pszFooter; + public int cchFooter; + public int iGroupId; + public uint stateMask; + public uint state; + public uint uAlign; + + public override string ToString() { + return "LVGROUP: header = " + pszHeader.ToString() + ", iGroupId = " + iGroupId.ToString(); + } + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(LVGROUP)); + } + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class LVINSERTMARK { + public uint cbSize = (uint)SizeOf(); + public int dwFlags; + public int iItem; + public int dwReserved = 0; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(LVINSERTMARK)); + } + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class LVTILEVIEWINFO { + public uint cbSize = (uint)SizeOf(); + public int dwMask; + public int dwFlags; + public SIZE sizeTile; + public int cLines; + public RECT rcLabelMargin; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(LVTILEVIEWINFO)); + } + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class NMLVCACHEHINT { + public NMHDR hdr; + public int iFrom; + public int iTo; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class NMLVDISPINFO + { + public NMHDR hdr; + public LVITEM item; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class NMLVDISPINFO_NOTEXT + { + public NMHDR hdr; + public LVITEM_NOTEXT item; + } + + [StructLayout(LayoutKind.Sequential)] + public class NMLVODSTATECHANGE { + public NMHDR hdr; + public int iFrom; + public int iTo; + public int uNewState; + public int uOldState; + } + + [StructLayout(LayoutKind.Sequential)] + public class CLIENTCREATESTRUCT { + public IntPtr hWindowMenu; + public int idFirstChild; + + public CLIENTCREATESTRUCT(IntPtr hmenu, int idFirst) { + hWindowMenu = hmenu; + idFirstChild = idFirst; + } + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class NMDATETIMECHANGE + { + public NMHDR nmhdr; + public int dwFlags; + public SYSTEMTIME st; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class NMDATETIMEFORMAT + { + public NMHDR nmhdr; + public string pszFormat; + public SYSTEMTIME st; + public string pszDisplay; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] + public string szDisplay; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class NMDATETIMEFORMATQUERY + { + public NMHDR nmhdr; + public string pszFormat; + public SIZE szMax; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class NMDATETIMEWMKEYDOWN + { + public NMHDR nmhdr; + public int nVirtKey; + public string pszFormat; + public SYSTEMTIME st; + } + + [StructLayout(LayoutKind.Sequential)] + public class COPYDATASTRUCT { + public int dwData; + public int cbData; + public IntPtr lpData; + } + + [StructLayout(LayoutKind.Sequential)] + public class NMHEADER { + public NMHDR nmhdr; + public int iItem; + public int iButton; + public IntPtr pItem; // HDITEM* + } + + [StructLayout(LayoutKind.Sequential)] + public class MOUSEHOOKSTRUCT { + // pt was a by-value POINT structure + public int pt_x = 0; + public int pt_y = 0; + public IntPtr hWnd = IntPtr.Zero; + public int wHitTestCode = 0; + public int dwExtraInfo = 0; + } + + [StructLayout(LayoutKind.Sequential)] + public class CHARRANGE + { + public int cpMin; + public int cpMax; + } + + [StructLayout(LayoutKind.Sequential, Pack=4)] + public class CHARFORMATW + { + public int cbSize = SizeOf(); + public int dwMask; + public int dwEffects; + public int yHeight; + public int yOffset; + public int crTextColor; + public byte bCharSet; + public byte bPitchAndFamily; + [MarshalAs(UnmanagedType.ByValArray, SizeConst=64)] + public byte[] szFaceName = new byte[64]; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(CHARFORMATW)); + } + } + + [StructLayout(LayoutKind.Sequential, Pack=4)] + public class CHARFORMATA + { + public int cbSize = SizeOf(); + public int dwMask; + public int dwEffects; + public int yHeight; + public int yOffset; + public int crTextColor; + public byte bCharSet; + public byte bPitchAndFamily; + [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)] + public byte[] szFaceName = new byte[32]; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(CHARFORMATA)); + } + } + + [StructLayout(LayoutKind.Sequential, Pack=4)] + public class CHARFORMAT2A + { + public int cbSize = SizeOf(); + public int dwMask; + public int dwEffects; + public int yHeight; + public int yOffset; + public int crTextColor; + public byte bCharSet; + public byte bPitchAndFamily; + [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)] + public byte[] szFaceName = new byte[32]; + public short wWeight; + public short sSpacing; + public int crBackColor; + public int lcid; + public int dwReserved; + public short sStyle; + public short wKerning; + public byte bUnderlineType; + public byte bAnimation; + public byte bRevAuthor; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(CHARFORMAT2A)); + } + } + + [StructLayout(LayoutKind.Sequential)] + public class TEXTRANGE + { + public CHARRANGE chrg; + public IntPtr lpstrText; /* allocated by caller, zero terminated by RichEdit */ + } + + [StructLayout(LayoutKind.Sequential)] + public class GETTEXTLENGTHEX + { // Taken from richedit.h: + public uint flags; // Flags (see GTL_XXX defines) + public uint codepage; // Code page for translation (CP_ACP for default, 1200 for Unicode) + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=4)] + public class SELCHANGE { + public NMHDR nmhdr; + public CHARRANGE chrg; + public int seltyp; + } + + [StructLayout(LayoutKind.Sequential)] + public class PARAFORMAT + { + public int cbSize = SizeOf(); + public int dwMask; + public short wNumbering; + public short wReserved; + public int dxStartIndent; + public int dxRightIndent; + public int dxOffset; + public short wAlignment; + public short cTabCount; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)] + public int[] rgxTabs; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(PARAFORMAT)); + } + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class FINDTEXT + { + public CHARRANGE chrg; + public string lpstrText; + } + + [StructLayout(LayoutKind.Sequential)] + public class REPASTESPECIAL + { + public int dwAspect; + public int dwParam; + } + + [StructLayout(LayoutKind.Sequential)] + public class ENLINK + { + public NMHDR nmhdr; + public int msg; + public IntPtr wParam; + public IntPtr lParam; + public CHARRANGE charrange; + } +#endif + internal abstract class CharBuffer + { + + /// + /// Critical: Extensive use of Marshal to allocate and manipulate + /// Character buffers. + /// + [SecurityCritical] + internal static CharBuffer CreateBuffer(int size) + { + if (Marshal.SystemDefaultCharSize == 1) + { + return new AnsiCharBuffer(size); + } + return new UnicodeCharBuffer(size); + } + + internal abstract IntPtr AllocCoTaskMem(); + internal abstract string GetString(); + internal abstract void PutCoTaskMem(IntPtr ptr); + internal abstract void PutString(string s); + internal abstract int Length{get;} + } + + + /// + /// Critical: Extensive use of Marshal to allocate and manipulate + /// Character buffers. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + internal class AnsiCharBuffer : CharBuffer + { + + internal byte[] buffer; + internal int offset; + + internal AnsiCharBuffer(int size) + { + buffer = new byte[size]; + } + + internal override int Length + { + get { return buffer.Length; } + } + + internal override IntPtr AllocCoTaskMem() + { + IntPtr result = Marshal.AllocCoTaskMem(buffer.Length); + Marshal.Copy(buffer, 0, result, buffer.Length); + + return result; + } + + internal override string GetString() + { + int i = offset; + while (i < buffer.Length && buffer[i] != 0) + i++; + + string result = Encoding.Default.GetString(buffer, offset, i - offset); + + if (i < buffer.Length) + i++; + + offset = i; + + return result; + } + + internal override void PutCoTaskMem(IntPtr ptr) + { + Marshal.Copy(ptr, buffer, 0, buffer.Length); + offset = 0; + } + + internal override void PutString(string s) + { + byte[] bytes = Encoding.Default.GetBytes(s); + int count = Math.Min(bytes.Length, buffer.Length - offset); + + Array.Copy(bytes, 0, buffer, offset, count); + + offset += count; + if (offset < buffer.Length) + buffer[offset++] = 0; + } + } + + /// + /// Critical: Extensive use of Marshal to allocate and manipulate + /// Character buffers. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + internal class UnicodeCharBuffer : CharBuffer + { + + internal char[] buffer; + internal int offset; + + internal UnicodeCharBuffer(int size) + { + buffer = new char[size]; + } + + internal override int Length + { + get { return buffer.Length; } + } + + internal override IntPtr AllocCoTaskMem() + { + IntPtr result = Marshal.AllocCoTaskMem(buffer.Length * 2); + Marshal.Copy(buffer, 0, result, buffer.Length); + return result; + } + + internal override String GetString() + { + int i = offset; + + while (i < buffer.Length && buffer[i] != 0) + i++; + + string result = new string(buffer, offset, i - offset); + + if (i < buffer.Length) + i++; + + offset = i; + return result; + } + + internal override void PutCoTaskMem(IntPtr ptr) + { + Marshal.Copy(ptr, buffer, 0, buffer.Length); + offset = 0; + } + + internal override void PutString(string s) + { + int count = Math.Min(s.Length, buffer.Length - offset); + + s.CopyTo(0, buffer, offset, count); + offset += count; + + if (offset < buffer.Length) + buffer[offset++] = (char)0; + } + } + +#if never + [StructLayout(LayoutKind.Sequential)] + public class ENDROPFILES + { + public NMHDR nmhdr; + public IntPtr hDrop; + public int cp; + public bool fProtected; + } + + [StructLayout(LayoutKind.Sequential)] + public class REQRESIZE + { + public NMHDR nmhdr; + public RECT rc; + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] + public class ENPROTECTED + { + public NMHDR nmhdr; + public int msg; + public IntPtr wParam; + public IntPtr lParam; + public CHARRANGE chrg; + } + + [StructLayout(LayoutKind.Sequential)] + public class ENPROTECTED64 + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst=56)] + public byte[] contents = new byte[56]; + } + + public class ActiveX { + public const int OCM__BASE = 0x2000; + public const int DISPID_VALUE = unchecked((int)0x0); + public const int DISPID_UNKNOWN = unchecked((int)0xFFFFFFFF); + public const int DISPID_AUTOSIZE = unchecked((int)0xFFFFFE0C); + public const int DISPID_BACKCOLOR = unchecked((int)0xFFFFFE0B); + public const int DISPID_BACKSTYLE = unchecked((int)0xFFFFFE0A); + public const int DISPID_BORDERCOLOR = unchecked((int)0xFFFFFE09); + public const int DISPID_BORDERSTYLE = unchecked((int)0xFFFFFE08); + public const int DISPID_BORDERWIDTH = unchecked((int)0xFFFFFE07); + public const int DISPID_DRAWMODE = unchecked((int)0xFFFFFE05); + public const int DISPID_DRAWSTYLE = unchecked((int)0xFFFFFE04); + public const int DISPID_DRAWWIDTH = unchecked((int)0xFFFFFE03); + public const int DISPID_FILLCOLOR = unchecked((int)0xFFFFFE02); + public const int DISPID_FILLSTYLE = unchecked((int)0xFFFFFE01); + public const int DISPID_FONT = unchecked((int)0xFFFFFE00); + public const int DISPID_FORECOLOR = unchecked((int)0xFFFFFDFF); + public const int DISPID_ENABLED = unchecked((int)0xFFFFFDFE); + public const int DISPID_HWND = unchecked((int)0xFFFFFDFD); + public const int DISPID_TABSTOP = unchecked((int)0xFFFFFDFC); + public const int DISPID_TEXT = unchecked((int)0xFFFFFDFB); + public const int DISPID_CAPTION = unchecked((int)0xFFFFFDFA); + public const int DISPID_BORDERVISIBLE = unchecked((int)0xFFFFFDF9); + public const int DISPID_APPEARANCE = unchecked((int)0xFFFFFDF8); + public const int DISPID_MOUSEPOINTER = unchecked((int)0xFFFFFDF7); + public const int DISPID_MOUSEICON = unchecked((int)0xFFFFFDF6); + public const int DISPID_PICTURE = unchecked((int)0xFFFFFDF5); + public const int DISPID_VALID = unchecked((int)0xFFFFFDF4); + public const int DISPID_READYSTATE = unchecked((int)0xFFFFFDF3); + public const int DISPID_REFRESH = unchecked((int)0xFFFFFDDA); + public const int DISPID_DOCLICK = unchecked((int)0xFFFFFDD9); + public const int DISPID_ABOUTBOX = unchecked((int)0xFFFFFDD8); + public const int DISPID_CLICK = unchecked((int)0xFFFFFDA8); + public const int DISPID_DBLCLICK = unchecked((int)0xFFFFFDA7); + public const int DISPID_KEYDOWN = unchecked((int)0xFFFFFDA6); + public const int DISPID_KEYPRESS = unchecked((int)0xFFFFFDA5); + public const int DISPID_KEYUP = unchecked((int)0xFFFFFDA4); + public const int DISPID_MOUSEDOWN = unchecked((int)0xFFFFFDA3); + public const int DISPID_MOUSEMOVE = unchecked((int)0xFFFFFDA2); + public const int DISPID_MOUSEUP = unchecked((int)0xFFFFFDA1); + public const int DISPID_ERROREVENT = unchecked((int)0xFFFFFDA0); + public const int DISPID_RIGHTTOLEFT = unchecked((int)0xFFFFFD9D); + public const int DISPID_READYSTATECHANGE = unchecked((int)0xFFFFFD9F); + public const int DISPID_AMBIENT_BACKCOLOR = unchecked((int)0xFFFFFD43); + public const int DISPID_AMBIENT_DISPLAYNAME = unchecked((int)0xFFFFFD42); + public const int DISPID_AMBIENT_FONT = unchecked((int)0xFFFFFD41); + public const int DISPID_AMBIENT_FORECOLOR = unchecked((int)0xFFFFFD40); + public const int DISPID_AMBIENT_LOCALEID = unchecked((int)0xFFFFFD3F); + public const int DISPID_AMBIENT_MESSAGEREFLECT = unchecked((int)0xFFFFFD3E); + public const int DISPID_AMBIENT_SCALEUNITS = unchecked((int)0xFFFFFD3D); + public const int DISPID_AMBIENT_TEXTALIGN = unchecked((int)0xFFFFFD3C); + public const int DISPID_AMBIENT_USERMODE = unchecked((int)0xFFFFFD3B); + public const int DISPID_AMBIENT_UIDEAD = unchecked((int)0xFFFFFD3A); + public const int DISPID_AMBIENT_SHOWGRABHANDLES = unchecked((int)0xFFFFFD39); + public const int DISPID_AMBIENT_SHOWHATCHING = unchecked((int)0xFFFFFD38); + public const int DISPID_AMBIENT_DISPLAYASDEFAULT = unchecked((int)0xFFFFFD37); + public const int DISPID_AMBIENT_SUPPORTSMNEMONICS = unchecked((int)0xFFFFFD36); + public const int DISPID_AMBIENT_AUTOCLIP = unchecked((int)0xFFFFFD35); + public const int DISPID_AMBIENT_APPEARANCE = unchecked((int)0xFFFFFD34); + public const int DISPID_AMBIENT_PALETTE = unchecked((int)0xFFFFFD2A); + public const int DISPID_AMBIENT_TRANSFERPRIORITY = unchecked((int)0xFFFFFD28); + public const int DISPID_AMBIENT_RIGHTTOLEFT = unchecked((int)0xFFFFFD24); + public const int DISPID_Name = unchecked((int)0xFFFFFCE0); + public const int DISPID_Delete = unchecked((int)0xFFFFFCDF); + public const int DISPID_Object = unchecked((int)0xFFFFFCDE); + public const int DISPID_Parent = unchecked((int)0xFFFFFCDD); + public const int DVASPECT_CONTENT = 0x1; + public const int DVASPECT_THUMBNAIL = 0x2; + public const int DVASPECT_ICON = 0x4; + public const int DVASPECT_DOCPRINT = 0x8; + public const int OLEMISC_RECOMPOSEONRESIZE = 0x1; + public const int OLEMISC_ONLYICONIC = 0x2; + public const int OLEMISC_INSERTNOTREPLACE = 0x4; + public const int OLEMISC_STATIC = 0x8; + public const int OLEMISC_CANTLINKINSIDE = 0x10; + public const int OLEMISC_CANLINKBYOLE1 = 0x20; + public const int OLEMISC_ISLINKOBJECT = 0x40; + public const int OLEMISC_INSIDEOUT = 0x80; + public const int OLEMISC_ACTIVATEWHENVISIBLE = 0x100; + public const int OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200; + public const int OLEMISC_INVISIBLEATRUNTIME = 0x400; + public const int OLEMISC_ALWAYSRUN = 0x800; + public const int OLEMISC_ACTSLIKEBUTTON = 0x1000; + public const int OLEMISC_ACTSLIKELABEL = 0x2000; + public const int OLEMISC_NOUIACTIVATE = 0x4000; + public const int OLEMISC_ALIGNABLE = 0x8000; + public const int OLEMISC_SIMPLEFRAME = 0x10000; + public const int OLEMISC_SETCLIENTSITEFIRST = 0x20000; + public const int OLEMISC_IMEMODE = 0x40000; + public const int OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000; + public const int OLEMISC_WANTSTOMENUMERGE = 0x100000; + public const int OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000; + public const int QACONTAINER_SHOWHATCHING = 0x1; + public const int QACONTAINER_SHOWGRABHANDLES = 0x2; + public const int QACONTAINER_USERMODE = 0x4; + public const int QACONTAINER_DISPLAYASDEFAULT = 0x8; + public const int QACONTAINER_UIDEAD = 0x10; + public const int QACONTAINER_AUTOCLIP = 0x20; + public const int QACONTAINER_MESSAGEREFLECT = 0x40; + public const int QACONTAINER_SUPPORTSMNEMONICS = 0x80; + public const int XFORMCOORDS_POSITION = 0x1; + public const int XFORMCOORDS_SIZE = 0x2; + public const int XFORMCOORDS_HIMETRICTOCONTAINER = 0x4; + public const int XFORMCOORDS_CONTAINERTOHIMETRIC = 0x8; + public const int PROPCAT_Nil = unchecked((int)0xFFFFFFFF); + public const int PROPCAT_Misc = unchecked((int)0xFFFFFFFE); + public const int PROPCAT_Font = unchecked((int)0xFFFFFFFD); + public const int PROPCAT_Position = unchecked((int)0xFFFFFFFC); + public const int PROPCAT_Appearance = unchecked((int)0xFFFFFFFB); + public const int PROPCAT_Behavior = unchecked((int)0xFFFFFFFA); + public const int PROPCAT_Data = unchecked((int)0xFFFFFFF9); + public const int PROPCAT_List = unchecked((int)0xFFFFFFF8); + public const int PROPCAT_Text = unchecked((int)0xFFFFFFF7); + public const int PROPCAT_Scale = unchecked((int)0xFFFFFFF6); + public const int PROPCAT_DDE = unchecked((int)0xFFFFFFF5); + public const int GC_WCH_SIBLING = 0x1; + public const int GC_WCH_CONTAINER = 0x2; + public const int GC_WCH_CONTAINED = 0x3; + public const int GC_WCH_ALL = 0x4; + public const int GC_WCH_FREVERSEDIR = 0x8000000; + public const int GC_WCH_FONLYNEXT = 0x10000000; + public const int GC_WCH_FONLYPREV = 0x20000000; + public const int GC_WCH_FSELECTED = 0x40000000; + public const int ALIGN_MIN = 0x0; + public const int ALIGN_NO_CHANGE = 0x0; + public const int ALIGN_TOP = 0x1; + public const int ALIGN_BOTTOM = 0x2; + public const int ALIGN_LEFT = 0x3; + public const int ALIGN_RIGHT = 0x4; + public const int ALIGN_MAX = 0x4; + public const int OLEVERBATTRIB_NEVERDIRTIES = 0x1; + public const int OLEVERBATTRIB_ONCONTAINERMENU = 0x2; + +#endif + +#if NEVER + public static class Util { + public static int MAKELONG(int low, int high) { + return (high << 16) | (low & 0xffff); + } + + public static IntPtr MAKELPARAM(int low, int high) { + return (IntPtr)(MAKELONG(low, high)); + } + + public static int HIWORD(int n) { + return (n >> 16) & 0xffff; + } + + public static int HIWORD(IntPtr n) { + return HIWORD( unchecked((int)(long)n) ); + } + + public static int LOWORD(int n) { + return n & 0xffff; + } + + public static int LOWORD(IntPtr n) { + return LOWORD( unchecked((int)(long)n) ); + } + + public static int SignedHIWORD(IntPtr n) { + return SignedHIWORD( unchecked((int)(long)n) ); + } + public static int SignedLOWORD(IntPtr n) { + return SignedLOWORD( unchecked((int)(long)n) ); + } + + public static int SignedHIWORD(int n) { + int i = (int)(short)((n >> 16) & 0xffff); + + return i; + } + + public static int SignedLOWORD(int n) { + int i = (int)(short)(n & 0xFFFF); + + return i; + } + + /// + /// Computes the string size that should be passed to a typical Win32 call. + /// This will be the character count under NT, and the ubyte count for Windows 95. + /// + public static int GetPInvokeStringLength(String s) { + if (s == null) { + return 0; + } + + if (Marshal.SystemDefaultCharSize == 2) { + return s.Length; + } + else { + if (s.Length == 0) { + return 0; + } + if (s.IndexOf('\0') > -1) { + return GetEmbededNullStringLengthAnsi(s); + } + else { + return lstrlen(s); + } + } + } + + private static int GetEmbededNullStringLengthAnsi(String s) { + int n = s.IndexOf('\0'); + if (n > -1) { + String left = s.Substring(0, n); + String right = s.Substring(n+1); + return GetPInvokeStringLength(left) + GetEmbededNullStringLengthAnsi(right) + 1; + } + else { + return GetPInvokeStringLength(s); + } + } + + [DllImport(ExternDll.Kernel32, CharSet=CharSet.Auto, BestFitMapping = false)] + private static extern int lstrlen(String s); + + } + +#endif + +#if never + + public enum tagTYPEKIND { + TKIND_ENUM = 0, + TKIND_RECORD = 1, + TKIND_MODULE = 2, + TKIND_INTERFACE = 3, + TKIND_DISPATCH = 4, + TKIND_COCLASS = 5, + TKIND_ALIAS = 6, + TKIND_UNION = 7, + TKIND_MAX = 8 + } + + [StructLayout(LayoutKind.Sequential)] + public class tagTLIBATTR { + public Guid guid; + [MarshalAs(UnmanagedType.U4)] + public int lcid; + public NativeMethods.tagSYSKIND syskind; + [MarshalAs(UnmanagedType.U2)] + public ushort wMajorVerNum; + [MarshalAs(UnmanagedType.U2)] + public ushort wMinorVerNum; + [MarshalAs(UnmanagedType.U2)] + public ushort wLibFlags; + } + + [StructLayout(LayoutKind.Sequential)] + public class tagTYPEDESC { + public IntPtr unionMember; + public short vt; + } + + [StructLayout(LayoutKind.Sequential)] + public struct tagPARAMDESC { + public IntPtr pparamdescex; + + [MarshalAs(UnmanagedType.U2)] + public ushort wParamFlags; + } +#endif + public static class CommonHandles { + static CommonHandles() { + } + + /// + /// Handle type for accelerator tables. + /// + public static readonly int Accelerator = HandleCollector.RegisterType("Accelerator", 80, 50); + + /// + /// handle type for cursors. + /// + public static readonly int Cursor = HandleCollector.RegisterType("Cursor", 20, 500); + + /// + /// Handle type for enhanced metafiles. + /// + public static readonly int EMF = HandleCollector.RegisterType("EnhancedMetaFile", 20, 500); + + /// + /// Handle type for file find handles. + /// + public static readonly int Find = HandleCollector.RegisterType("Find", 0, 1000); + + /// + /// Handle type for GDI objects. + /// + public static readonly int GDI = HandleCollector.RegisterType("GDI", 50, 500); + + /// + /// Handle type for HDC's that count against the Win98 limit of five DC's. HDC's + /// which are not scarce, such as HDC's for bitmaps, are counted as GDIHANDLE's. + /// + public static readonly int HDC = HandleCollector.RegisterType("HDC", 100, 2); // wait for 2 dc's before collecting + + /// + /// Handle type for icons. + /// + public static readonly int Icon = HandleCollector.RegisterType("Icon", 20, 500); + + /// + /// Handle type for kernel objects. + /// + public static readonly int Kernel = HandleCollector.RegisterType("Kernel", 0, 1000); + + /// + /// Handle type for files. + /// + public static readonly int Menu = HandleCollector.RegisterType("Menu", 30, 1000); + + /// + /// Handle type for windows. + /// + public static readonly int Window = HandleCollector.RegisterType("Window", 5, 1000); + } +#if never + public enum tagSYSKIND { + SYS_WIN16 = 0, + SYS_MAC = 2 + } + + public delegate bool MonitorEnumProc(IntPtr monitor, IntPtr hdc, IntPtr lprcMonitor, IntPtr lParam); + + /// + /// Critical : Elevates to UnmanagedCode permissions + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("A7ABA9C1-8983-11cf-8F20-00805F2CD064"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IProvideMultipleClassInfo { + // since the inheritance doesn't seem to work... + // these are from IProvideClassInfo & IProvideClassInfo2 + [PreserveSig] + UnsafeNativeMethods.ITypeInfo GetClassInfo(); + + [PreserveSig] + int GetGUID(int dwGuidKind, [In, Out] ref Guid pGuid); + + [PreserveSig] + int GetMultiTypeInfoCount([In, Out] ref int pcti); + + // we use arrays for most of these since we never use them anyway. + [PreserveSig] + int GetInfoOfIndex(int iti, int dwFlags, + [In, Out] + ref UnsafeNativeMethods.ITypeInfo pTypeInfo, + int pTIFlags, + int pcdispidReserved, + IntPtr piidPrimary, + IntPtr piidSource); + } + + [StructLayout(LayoutKind.Sequential)] + public class EVENTMSG { + public int message; + public int paramL; + public int paramH; + public int time; + public IntPtr hwnd; + } + + /// + /// Critical : Elevates to UnmanagedCode permissions + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("B196B283-BAB4-101A-B69C-00AA00341D07"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IProvideClassInfo { + [return: MarshalAs(UnmanagedType.Interface)] + UnsafeNativeMethods.ITypeInfo GetClassInfo(); + } + + [StructLayout(LayoutKind.Sequential)] + public sealed class tagTYPEATTR { + public Guid guid; + [MarshalAs(UnmanagedType.U4)] + public uint lcid; + [MarshalAs(UnmanagedType.U4)] + public uint dwReserved; + public int memidConstructor; + public int memidDestructor; + public IntPtr lpstrSchema; + [MarshalAs(UnmanagedType.U4)] + public uint cbSizeInstance; + public /*NativeMethods.tagTYPEKIND*/ int typekind; + [MarshalAs(UnmanagedType.U2)] + public ushort cFuncs; + [MarshalAs(UnmanagedType.U2)] + public ushort cVars; + [MarshalAs(UnmanagedType.U2)] + public ushort cImplTypes; + [MarshalAs(UnmanagedType.U2)] + public ushort cbSizeVft; + [MarshalAs(UnmanagedType.U2)] + public ushort cbAlignment; + [MarshalAs(UnmanagedType.U2)] + public ushort wTypeFlags; + [MarshalAs(UnmanagedType.U2)] + public ushort wMajorVerNum; + [MarshalAs(UnmanagedType.U2)] + public ushort wMinorVerNum; + + // SBurke these are inline too + //public NativeMethods.tagTYPEDESC tdescAlias; + [MarshalAs(UnmanagedType.U4)] + public int tdescAlias_unionMember; + + [MarshalAs(UnmanagedType.U2)] + public short tdescAlias_vt; + + //public NativeMethods.tagIDLDESC idldescType; + [MarshalAs(UnmanagedType.U4)] + public int idldescType_dwReserved; + + [MarshalAs(UnmanagedType.U2)] + public short idldescType_wIDLFlags; + + + public tagTYPEDESC Get_tdescAlias(){ + tagTYPEDESC td = new tagTYPEDESC(); + td.unionMember = (IntPtr)this.tdescAlias_unionMember; + td.vt = this.tdescAlias_vt; + return td; + } + + public tagIDLDESC Get_idldescType(){ + tagIDLDESC id = new tagIDLDESC(); + id.dwReserved = this.idldescType_dwReserved; + id.wIDLFlags = this.idldescType_wIDLFlags; + return id; + } + } + + public enum tagVARFLAGS { + VARFLAG_FREADONLY = 1, + VARFLAG_FSOURCE = 0x2, + VARFLAG_FBINDABLE = 0x4, + VARFLAG_FREQUESTEDIT = 0x8, + VARFLAG_FDISPLAYBIND = 0x10, + VARFLAG_FDEFAULTBIND = 0x20, + VARFLAG_FHIDDEN = 0x40, + VARFLAG_FDEFAULTCOLLELEM = 0x100, + VARFLAG_FUIDEFAULT = 0x200, + VARFLAG_FNONBROWSABLE = 0x400, + VARFLAG_FREPLACEABLE = 0x800, + VARFLAG_FIMMEDIATEBIND = 0x1000 + } + + [StructLayout(LayoutKind.Sequential)] + public sealed class tagELEMDESC { + public NativeMethods.tagTYPEDESC tdesc; + public NativeMethods.tagPARAMDESC paramdesc; + } + + public enum tagVARKIND { + VAR_PERINSTANCE = 0, + VAR_STATIC = 1, + VAR_CONST = 2, + VAR_DISPATCH = 3 + } + + [StructLayout(LayoutKind.Sequential)] + public struct tagIDLDESC { + [MarshalAs(UnmanagedType.U4)] + public int dwReserved; + [MarshalAs(UnmanagedType.U2)] + public ushort wIDLFlags; + } + + public struct RGBQUAD { + public byte rgbBlue; + public byte rgbGreen; + public byte rgbRed; + public byte rgbReserved; + } + + [StructLayout(LayoutKind.Sequential)] + public class BITMAPINFO_ARRAY { + public BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER(); + + [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=BITMAPINFO_MAX_COLORSIZE*4)] + public byte[] bmiColors; // RGBQUAD structs... Blue-Green-Red-Reserved, repeat... + } + + [StructLayout(LayoutKind.Sequential)] + public struct PALETTEENTRY { + public byte peRed; + public byte peGreen; + public byte peBlue; + public byte peFlags; + } + + [StructLayout(LayoutKind.Sequential)] + public struct BITMAPINFO_FLAT { + public int bmiHeader_biSize;// = Marshal.SizeOf(typeof(BITMAPINFOHEADER)); + public int bmiHeader_biWidth; + public int bmiHeader_biHeight; + public short bmiHeader_biPlanes; + public short bmiHeader_biBitCount; + public int bmiHeader_biCompression; + public int bmiHeader_biSizeImage; + public int bmiHeader_biXPelsPerMeter; + public int bmiHeader_biYPelsPerMeter; + public int bmiHeader_biClrUsed; + public int bmiHeader_biClrImportant; + + [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=BITMAPINFO_MAX_COLORSIZE*4)] + public byte[] bmiColors; // RGBQUAD structs... Blue-Green-Red-Reserved, repeat... + } + + + /// + /// This method takes a file URL and converts it to a local path. The trick here is that + /// if there is a '#' in the path, everything after this is treated as a fragment. So + /// we need to append the fragment to the end of the path. + /// + internal static string GetLocalPath(string fileName) { + System.Diagnostics.Debug.Assert(fileName != null && fileName.Length > 0, "Cannot get local path, fileName is not valid"); + + Uri uri = new Uri(fileName, true); + return uri.LocalPath + uri.Fragment; + } + +#endif + + public const int PBT_APMPOWERSTATUSCHANGE = 0x000A; + + [StructLayout(LayoutKind.Sequential)] + public struct SYSTEM_POWER_STATUS { + public byte ACLineStatus; + public byte BatteryFlag; + public byte BatteryLifePercent; + public byte Reserved1; + public int BatteryLifeTime; + public int BatteryFullLifeTime; + } + +#if never + [StructLayout(LayoutKind.Sequential)] + internal class DLLVERSIONINFO + { + internal uint cbSize; + internal uint dwMajorVersion; + internal uint dwMinorVersion; + internal uint dwBuildNumber; + internal uint dwPlatformID; + } + + public enum OLERENDER + { + OLERENDER_NONE = 0, + OLERENDER_DRAW = 1, + OLERENDER_FORMAT = 2, + OLERENDER_ASIS = 3 + } + + // Theming/Visual Styles stuff + public const int STAP_ALLOW_NONCLIENT = (1 << 0); + public const int STAP_ALLOW_CONTROLS = (1 << 1); + public const int STAP_ALLOW_WEBCONTENT = (1 << 2); + + public const int PS_NULL = 5; + public const int PS_INSIDEFRAME = 6; + + public const int PS_GEOMETRIC = 0x00010000; + public const int PS_ENDCAP_SQUARE = 0x00000100; + + public const int MM_HIMETRIC = 3; + +#endif + + // WinEvent +#if never + public const int EVENT_MIN = 0x00000001; + public const int EVENT_MAX = 0x7FFFFFFF; + + public const int EVENT_SYSTEM_SOUND = 0x0001; + public const int EVENT_SYSTEM_ALERT = 0x0002; + public const int EVENT_SYSTEM_FOREGROUND = 0x0003; + public const int EVENT_SYSTEM_MENUSTART = 0x0004; + public const int EVENT_SYSTEM_MENUEND = 0x0005; + public const int EVENT_SYSTEM_MENUPOPUPSTART = 0x0006; + public const int EVENT_SYSTEM_MENUPOPUPEND = 0x0007; + public const int EVENT_SYSTEM_CAPTURESTART = 0x0008; + public const int EVENT_SYSTEM_CAPTUREEND = 0x0009; +#endif + public const int EVENT_SYSTEM_MOVESIZESTART = 0x000A; + public const int EVENT_SYSTEM_MOVESIZEEND = 0x000B; +#if never + public const int EVENT_SYSTEM_CONTEXTHELPSTART = 0x000C; + public const int EVENT_SYSTEM_CONTEXTHELPEND = 0x000D; + public const int EVENT_SYSTEM_DRAGDROPSTART = 0x000E; + public const int EVENT_SYSTEM_DRAGDROPEND = 0x000F; + public const int EVENT_SYSTEM_DIALOGSTART = 0x0010; + public const int EVENT_SYSTEM_DIALOGEND = 0x0011; + public const int EVENT_SYSTEM_SCROLLINGSTART = 0x0012; + public const int EVENT_SYSTEM_SCROLLINGEND = 0x0013; + public const int EVENT_SYSTEM_SWITCHEND = 0x0015; + public const int EVENT_SYSTEM_MINIMIZESTART = 0x0016; + public const int EVENT_SYSTEM_MINIMIZEEND = 0x0017; + public const int EVENT_SYSTEM_PAINT = 0x0019; + public const int EVENT_CONSOLE_CARET = 0x4001; + public const int EVENT_CONSOLE_UPDATE_REGION = 0x4002; + public const int EVENT_CONSOLE_UPDATE_SIMPLE = 0x4003; + public const int EVENT_CONSOLE_UPDATE_SCROLL = 0x4004; + public const int EVENT_CONSOLE_LAYOUT = 0x4005; + public const int EVENT_CONSOLE_START_APPLICATION = 0x4006; + public const int EVENT_CONSOLE_END_APPLICATION = 0x4007; + public const int EVENT_OBJECT_CREATE = 0x8000; + public const int EVENT_OBJECT_DESTROY = 0x8001; + public const int EVENT_OBJECT_SHOW = 0x8002; + public const int EVENT_OBJECT_HIDE = 0x8003; + public const int EVENT_OBJECT_REORDER = 0x8004; + public const int EVENT_OBJECT_SELECTION = 0x8006; + public const int EVENT_OBJECT_SELECTIONADD = 0x8007; + public const int EVENT_OBJECT_SELECTIONREMOVE = 0x8008; + public const int EVENT_OBJECT_SELECTIONWITHIN = 0x8009; + public const int EVENT_OBJECT_LOCATIONCHANGE = 0x800B; + public const int EVENT_OBJECT_NAMECHANGE = 0x800C; + public const int EVENT_OBJECT_DESCRIPTIONCHANGE = 0x800D; + public const int EVENT_OBJECT_VALUECHANGE = 0x800E; + public const int EVENT_OBJECT_PARENTCHANGE = 0x800F; + public const int EVENT_OBJECT_HELPCHANGE = 0x8010; + public const int EVENT_OBJECT_DEFACTIONCHANGE = 0x8011; + public const int EVENT_OBJECT_ACCELERATORCHANGE = 0x8012; +#endif + + public const int EVENT_OBJECT_STATECHANGE = 0x800A; + public const int EVENT_OBJECT_FOCUS = 0x8005; + public const int OBJID_CLIENT = unchecked(unchecked((int)0xFFFFFFFC)); + public const int WINEVENT_OUTOFCONTEXT = 0x0000; +#if never + public const int WINEVENT_SKIPOWNTHREAD = 0x0001; + public const int WINEVENT_SKIPOWNPROCESS = 0x0002; + public const int WINEVENT_INCONTEXT = 0x0004; +#endif + + // the delegate passed to USER for receiving a WinEvent + internal delegate void WinEventProcDef (int winEventHook, int eventId, IntPtr hwnd, int idObject, int idChild, int eventThread, int eventTime); + + #region WebBrowser Related Definitions + /// + /// Specifies the ReadyState of the WebBrowser control. + /// Returned by the IWebBrowser2.ReadyState property. + /// + public enum WebBrowserReadyState + { + UnInitialized = 0, + Loading = 1, + Loaded = 2, + Interactive = 3, + Complete = 4 + } + +#if never + public const int URLACTION_JAVA_PERMISSIONS = 0x00001C00, + URLACTION_CREDENTIALS_USE = 0x00001A00, + URLACTION_CHANNEL_SOFTDIST_PERMISSIONS = 0x00001E05, + URLACTION_HTML_FONT_DOWNLOAD = 0x00001604; + + public const int URLPOLICY_QUERY = 0x01, + URLPOLICY_ALLOW = 0x00, + URLPOLICY_DISALLOW = 0x03, + URLPOLICY_JAVA_PROHIBIT = 0x00000000, + URLPOLICY_CREDENTIALS_MUST_PROMPT_USER = 0x00010000, + URLPOLICY_CHANNEL_SOFTDIST_PROHIBIT = 0x00010000; +#endif + #endregion WebBrowser Related Definitions + + [StructLayout(LayoutKind.Sequential)] + public struct RAWINPUTDEVICELIST + { + public IntPtr hDevice; + public uint dwType; + } + + [StructLayout(LayoutKind.Sequential)] + public struct RID_DEVICE_INFO_MOUSE + { + public uint dwId; + public uint dwNumberOfButtons; + public uint dwSampleRate; + } + + [StructLayout(LayoutKind.Sequential)] + public struct RID_DEVICE_INFO_KEYBOARD + { + public uint dwType; + public uint dwSubType; + public uint dwKeyboardMode; + public uint dwNumberOfFunctionKeys; + public uint dwNumberOfIndicators; + public uint dwNumberOfKeysTotal; + } + + [StructLayout(LayoutKind.Sequential)] + public struct RID_DEVICE_INFO_HID + { + public uint dwVendorId; + public uint dwProductId; + public uint dwVersionNumber; + public ushort usUsagePage; + public ushort usUsage; + } + + [StructLayout(LayoutKind.Explicit)] + public struct RID_DEVICE_INFO + { + [FieldOffset(0)] + public uint cbSize; + [FieldOffset(4)] + public uint dwType; + [FieldOffset(8)] + public RID_DEVICE_INFO_MOUSE mouse; + [FieldOffset(8)] + public RID_DEVICE_INFO_KEYBOARD keyboard; + [FieldOffset(8)] + public RID_DEVICE_INFO_HID hid; + } + + public const uint RIDI_DEVICEINFO = 0x2000000b; + public const uint RIM_TYPEHID = 2; + public const ushort HID_USAGE_PAGE_DIGITIZER = 0x0D; + public const ushort HID_USAGE_DIGITIZER_DIGITIZER = 1; + public const ushort HID_USAGE_DIGITIZER_PEN = 2; + public const ushort HID_USAGE_DIGITIZER_LIGHTPEN = 3; + public const ushort HID_USAGE_DIGITIZER_TOUCHSCREEN = 4; + + [StructLayout(LayoutKind.Sequential)] + public struct BLENDFUNCTION + { + public byte BlendOp; + public byte BlendFlags; + public byte SourceConstantAlpha; + public byte AlphaFormat; + } + + public const int AC_SRC_OVER = 0x00000000; + public const int ULW_COLORKEY = 0x00000001; + public const int ULW_ALPHA = 0x00000002; + public const int ULW_OPAQUE = 0x00000004; + + /// + /// Contains values that indicate the type of session information to retrieve + /// in a call to the WTSQuerySessionInformation function. + /// + public enum WTS_INFO_CLASS + { + /// + /// A null-terminated string that contains the name of the initial program that Remote Desktop Services runs when the user logs on. + /// + WTSInitialProgram = 0, + /// + /// A null-terminated string that contains the published name of the application that the session is running. + /// + /// + /// Windows Server 2008 R2, Windows 7, Windows Server 2008 and Windows Vista: This value is not supported + /// + WTSApplicationName = 1, + /// + /// A null-terminated string that contains the default directory used when launching the initial program. + /// + WTSWorkingDirectory = 2, + /// + /// This value is not used. + /// + WTSOEMId = 3, + /// + /// A ULONG value that contains the session identifier. + /// + WTSSessionId = 4, + /// + /// A null-terminated string that contains the name of the user associated with the session. + /// + WTSUserName = 5, + /// + /// A null-terminated string that contains the name of the Remote Desktop Services session. + /// + /// + /// Despite its name, specifying this type does not return the window station name. Rather, it returns + /// the name of the Remote Desktop Services session. Each Remote Desktop Services session is associated + /// with an interactive window station. Because the only supported window station name for an interactive + /// window station is "WinSta0", each session is associated with its own "WinSta0" window station. For more + /// information, Window Stations + /// + WTSWinStationName = 6, + /// + /// A null-terminated string that contains the name of the domain to which the logged-on user belongs. + /// + WTSDomainName = 7, + /// + /// The session's current connection state. For more information, + /// + WTSConnectState = 8, + /// + /// A ULONG value that contains the build number of the client. + /// + WTSClientBuildNumber = 9, + /// + /// A null-terminated string that contains the name of the client. + /// + WTSClientName = 10, + /// + /// A null-terminated string that contains the directory in which the client + /// is installed. + /// + WTSClientDirectory = 11, + /// + /// A USHORT client-specific product identifier. + /// + WTSClientProductId = 12, + /// + /// A ULONG value that contains a client-specific hardware identifier. This option + /// is reserved + /// for future use. + /// WTSQuerySessionInformation will always return a value of 0. + /// + WTSClientHardwareId = 13, + /// + /// The network type and network address of the client. For more information, + /// see WTS_CLIENT_ADDRESS. + /// The IP address is offset by two bytes from the start of the Address member of the + /// WTS_CLIENT_ADDRESS structure. + /// + WTSClientAddress = 14, + /// + /// Information about the display resolution of the client. For more information, + /// see WTS_CLIENT_DISPLAY. + /// + WTSClientDisplay = 15, + /// + /// A USHORT value that specifies information about the protocol type for the session. + /// This is one of the following values: + /// 0 : The console session. + /// 1 : This value is retained for legacy purposes. + /// 2 : The RDP protocol. + /// + WTSClientProtocolType = 16, + /// + /// This value returns FALSE. If you call GetLastError to get extended error information, + /// GetLastError returns ERROR_NOT_SUPPORTED. + /// + /// Windows Server 2008 and Windows Vista: This value is not used. + WTSIdleTime = 17, + /// + /// This value returns FALSE. If you call GetLastError to get extended error information, + /// GetLastError returns ERROR_NOT_SUPPORTED. + /// + /// Windows Server 2008 and Windows Vista: This value is not used. + WTSLogonTime = 18, + /// + /// This value returns FALSE. If you call GetLastError to get extended error information, + /// GetLastError returns ERROR_NOT_SUPPORTED. + /// + /// Windows Server 2008 and Windows Vista: This value is not used. + WTSIncomingBytes = 19, + /// + /// This value returns FALSE. If you call GetLastError to get extended error information, + /// GetLastError returns ERROR_NOT_SUPPORTED. + /// + /// Windows Server 2008 and Windows Vista: This value is not used. + WTSOutgoingBytes = 20, + /// + /// This value returns FALSE. If you call GetLastError to get extended error information, + /// GetLastError returns ERROR_NOT_SUPPORTED. + /// + /// Windows Server 2008 and Windows Vista: This value is not used. + WTSIncomingFrames = 21, + /// + /// This value returns FALSE. If you call GetLastError to get extended error information, + /// GetLastError returns ERROR_NOT_SUPPORTED. + /// + /// Windows Server 2008 and Windows Vista: This value is not used. + WTSOutgoingFrames = 22, + /// + /// Information about a Remote Desktop Connection (RDC) client. For more information, + /// see WTSCLIENT. + /// + WTSClientInfo = 23, + /// + /// Information about a client session on a RD Session Host server. For more information, + /// see WTSINFO. + /// + WTSSessionInfo = 24, + /// + /// Extended information about a session on a RD Session Host server. For more information, + /// see WTSINFOEX. + /// + /// Windows Server 2008 and Windows Vista: This value is not supported. + WTSSessionInfoEx = 25, + /// + /// A WTSCONFIGINFO structure that contains information about the configuration of a RD + /// Session Host server. + /// + /// Windows Server 2008 and Windows Vista: This value is not supported. + WTSConfigInfo = 26, + /// + /// This value is not supported. + /// + WTSValidationInfo = 27, + /// + /// A WTS_SESSION_ADDRESS structure that contains the IPv4 address assigned to the session. + /// If the session does not have a virtual IP address, the WTSQuerySessionInformation function + /// returns ERROR_NOT_SUPPORTED. + /// + /// Windows Server 2008 and Windows Vista: This value is not supported. + WTSSessionAddressV4 = 28, + /// + /// Determines whether the current session is a remote session. The WTSQuerySessionInformation + /// function returns a value of TRUE to indicate that the current session is a remote session, + /// and FALSE to indicate that the current session is a local session. This value can only be + /// used for the local machine, so the hServer parameter of the WTSQuerySessionInformation + /// function must contain WTS_CURRENT_SERVER_HANDLE. + /// + /// Windows Server 2008 and Windows Vista: This value is not supported. + WTSIsRemoteSession = 29 + } + + /// + /// Specifies the connection state of a Remote Desktop Services session. + /// ; + /// + /// Only WTSActive represents a fully connected user session. All other + /// states represent a disconnected user session. + /// + public enum WTS_CONNECTSTATE_CLASS + { + /// + /// A user is logged on to the WinStation. + /// + WTSActive = 0, + /// + /// The WinStation is connected to the client. + /// + WTSConnected = 1, + /// + /// The WinStation is in the process of connecting to the client. + /// + WTSConnectQuery = 2, + /// + /// The WinStation is shadowing another WinStation. + /// + WTSShadow = 3, + /// + /// The WinStation is active but the client is disconnected. + /// + WTSDisconnected = 4, + /// + /// The WinStation is waiting for a client to connect. + /// + WTSIdle = 5, + /// + /// The WinStation is listening for a connection. A listener session waits for requests for + /// new client connections. + /// No user is logged on a listener session. A listener session cannot be reset, shadowed, or + /// changed to a regular client session. + /// + WTSListen = 6, + /// + /// The WinStation is being reset. + /// + WTSReset = 7, + /// + /// The WinStation is down due to an error. + /// + WTSDown = 8, + /// + /// The WinStation is initializing. + /// + WTSInit = 9 + } + + /// + /// Specifies the current server + /// + public static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero; + + /// + /// Specifies the current session (SessionId) + /// + public const int WTS_CURRENT_SESSION = -1; + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsOther.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsOther.cs new file mode 100644 index 00000000000..7555c4b24b0 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsOther.cs @@ -0,0 +1,1793 @@ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +namespace MS.Win32 +{ + using Accessibility; + using System; + using System.Runtime.ConstrainedExecution; + using System.Runtime.InteropServices; + using System.Security; + using System.Security.Permissions; + using System.Collections; + using System.Diagnostics; + using System.IO; + using System.Text; + using MS.Win32; + using Microsoft.Win32.SafeHandles; + + +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif UIAUTOMATIONTYPES + using MS.Internal.UIAutomationTypes; +#elif DRT + using MS.Internal.Drt; +#else +#error Attempt to use FriendAccessAllowedAttribute from an unknown assembly. + using MS.Internal.YourAssemblyName; +#endif + + [FriendAccessAllowed] + internal partial class NativeMethods + { + // Translates Win32 error codes into HRESULTs. + public static int MakeHRFromErrorCode(int errorCode) + { + Debug.Assert((0xFFFF0000 & errorCode) == 0); + return unchecked(((int)0x80070000) | errorCode); + } + + public const int FEATURE_OBJECT_CACHING = 0 ; + public const int FEATURE_ZONE_ELEVATION = 1; + public const int FEATURE_MIME_HANDLING = 2; + public const int FEATURE_MIME_SNIFFING = 3; + public const int FEATURE_WINDOW_RESTRICTIONS = 4; + public const int FEATURE_WEBOC_POPUPMANAGEMENT = 5; + public const int FEATURE_BEHAVIORS = 6; + public const int FEATURE_DISABLE_MK_PROTOCOL = 7; + public const int FEATURE_LOCALMACHINE_LOCKDOWN = 8; + public const int FEATURE_SECURITYBAND = 9; + public const int FEATURE_RESTRICT_ACTIVEXINSTALL = 10; + public const int FEATURE_VALIDATE_NAVIGATE_URL = 11; + public const int FEATURE_RESTRICT_FILEDOWNLOAD = 12; + public const int FEATURE_ADDON_MANAGEMENT = 13; + public const int FEATURE_PROTOCOL_LOCKDOWN = 14; + public const int FEATURE_HTTP_USERNAME_PASSWORD_DISABLE = 15; + public const int FEATURE_SAFE_BINDTOOBJECT = 16; + public const int FEATURE_UNC_SAVEDFILECHECK = 17; + public const int FEATURE_GET_URL_DOM_FILEPATH_UNENCODED = 18; + + // IE7 and higher + public const int FEATURE_TABBED_BROWSING = 19; + public const int FEATURE_SSLUX = 20; + public const int FEATURE_DISABLE_NAVIGATION_SOUNDS = 21; + public const int FEATURE_DISABLE_LEGACY_COMPRESSION = 22; + public const int FEATURE_FORCE_ADDR_AND_STATUS = 23; + public const int FEATURE_XMLHTTP = 24; + public const int FEATURE_DISABLE_TELNET_PROTOCOL = 25; + public const int FEATURE_FEEDS = 26; + public const int FEATURE_BLOCK_INPUT_PROMPTS = 27; + + public const int GET_FEATURE_FROM_PROCESS = 0x00000002; + public const int SET_FEATURE_ON_PROCESS = 0x00000002; + + public const int URLZONE_LOCAL_MACHINE = 0; + public const int URLZONE_INTRANET = URLZONE_LOCAL_MACHINE + 1; + public const int URLZONE_TRUSTED = URLZONE_INTRANET + 1; + public const int URLZONE_INTERNET = URLZONE_TRUSTED + 1; + public const int URLZONE_UNTRUSTED = URLZONE_INTERNET + 1; + + public const byte URLPOLICY_ALLOW = 0x00; + public const byte URLPOLICY_QUERY = 0x01; + public const byte URLPOLICY_DISALLOW = 0x03; + + public const int URLACTION_FEATURE_ZONE_ELEVATION = 0x00002101; + public const int PUAF_NOUI = 0x00000001; + public const int MUTZ_NOSAVEDFILECHECK = 0x00000001; + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode )] + internal sealed class OSVERSIONINFOEX + { + public int osVersionInfoSize = SizeOf(); + public int majorVersion = 0; + public int minorVersion = 0; + public int buildNumber = 0; + public int platformId = 0; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] + public string csdVersion = null; + public short servicePackMajor = 0; + public short servicePackMinor = 0; + public short suiteMask = 0; + public byte productType = 0; + public byte reserved = 0; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(OSVERSIONINFOEX)); + } + } + [ComImport, Guid("79eac9ee-baf9-11ce-8c82-00aa004ba90b"), System.Runtime.InteropServices.InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IInternetSecurityMgrSite + { + void GetWindow( /* [out] */ ref IntPtr phwnd) ; + void EnableModeless( /* [in] */ bool fEnable) ; + } + + [StructLayout(LayoutKind.Sequential)] + internal class OLECMD { + [MarshalAs(UnmanagedType.U4)] + public int cmdID = 0; + [MarshalAs(UnmanagedType.U4)] + public int cmdf = 0; + + } + + // Helper GUID type for nullability requirement in IOleCommandTarget.Exec. + [StructLayout(LayoutKind.Sequential)] + internal class GUID + { + public Guid guid; + + public GUID(Guid guid) + { + this.guid = guid; + } + } + + /// + /// Critical - Applies SuppressUnmanagedCodeSecurity. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [ComVisible(true), ComImport(), Guid("B722BCCB-4E68-101B-A2BC-00AA00404770")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IOleCommandTarget + { + + [SecurityCritical] + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int QueryStatus( + GUID pguidCmdGroup, /* nullable GUID */ + int cCmds, + [In, Out] + OLECMD prgCmds, + [In, Out] + IntPtr pCmdText); + + [SecurityCritical] + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int Exec( + GUID pguidCmdGroup, /* nullable GUID */ + int nCmdID, + int nCmdexecopt, + // we need to have this an array because callers need to be able to specify NULL or VT_NULL + [In, MarshalAs(UnmanagedType.LPArray)] + Object[] pvaIn, + int pvaOut); + } + + [ComVisible(true), StructLayout(LayoutKind.Sequential)] + internal class DOCHOSTUIINFO { + [MarshalAs(UnmanagedType.U4)] + internal int cbSize = SizeOf(); + [MarshalAs(UnmanagedType.I4)] + internal int dwFlags; + [MarshalAs(UnmanagedType.I4)] + internal int dwDoubleClick; + [MarshalAs(UnmanagedType.I4)] + internal int dwReserved1 = 0; + [MarshalAs(UnmanagedType.I4)] + internal int dwReserved2 = 0; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(DOCHOSTUIINFO)); + } + } + + + public enum DOCHOSTUIFLAG { + DIALOG = 0x1, + DISABLE_HELP_MENU = 0x2, + NO3DBORDER = 0x4, + SCROLL_NO = 0x8, + DISABLE_SCRIPT_INACTIVE = 0x10, + OPENNEWWIN = 0x20, + DISABLE_OFFSCREEN = 0x40, + FLAT_SCROLLBAR = 0x80, + DIV_BLOCKDEFAULT = 0x100, + ACTIVATE_CLIENTHIT_ONLY = 0x200, + NO3DOUTERBORDER = 0x00200000, + ENABLE_FORMS_AUTOCOMPLETE = 0x00004000, + ENABLE_INPLACE_NAVIGATION = 0x00010000, + IME_ENABLE_RECONVERSION = 0x00020000, + THEME = 0x00040000, + NOTHEME = 0x80000, + DISABLE_COOKIE = 0x400, + NOPICS = 0x100000, + DISABLE_EDIT_NS_FIXUP = 0x400000, + LOCAL_MACHINE_ACCESS_CHECK= 0x800000, + DISABLE_UNTRUSTEDPROTOCOL = 0x1000000, + HOST_NAVIGATES = 0x2000000, + ENABLE_REDIRECT_NOTIFICATION = 0x4000000 + } + + public enum DOCHOSTUIDBLCLICK { + DEFAULT = 0x0, + SHOWPROPERTIES = 0x1, + SHOWCODE = 0x2 + } + + /// + /// Critical : Elevates to UnmanagedCode permissions + /// + [SecurityCritical] + [DllImport(ExternDll.Gdi32, ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + internal static extern IntPtr SetEnhMetaFileBits(uint cbBuffer, byte[] buffer); + + [StructLayout(LayoutKind.Sequential)] + internal class ICONINFO + { + public bool fIcon = false; + public int xHotspot = 0; + public int yHotspot = 0; + public BitmapHandle hbmMask = null; + public BitmapHandle hbmColor = null; + } + + internal abstract class WpfSafeHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private int _collectorId; + + /// + /// Critical:This code calls into a base class which is protected by link demand and by inheritance demand + /// + [SecurityCritical] + protected WpfSafeHandle(bool ownsHandle, int collectorId) : base(ownsHandle) + { + HandleCollector.Add(collectorId); + _collectorId = collectorId; + } + + /// + /// Critical: Conceptually, this would be accessing critical data as it's in the destroy call path. + /// TreatAsSafe: This is just destroying a handle that this object owns. + /// + [SecurityCritical, SecurityTreatAsSafe] + protected override void Dispose(bool disposing) + { + HandleCollector.Remove(_collectorId); + base.Dispose(disposing); + } + + // ReleaseHandle implementation is deferred to derived classes. + // protected override bool ReleaseHandle() {} + } + + internal sealed class BitmapHandle : WpfSafeHandle + { + /// + /// Critical: This code calls into a base class which is protected by a SecurityCritical constructor. + /// + [SecurityCritical] + private BitmapHandle() : this(true) + { + } + + /// + /// Critical: This code calls into a base class which is protected by a SecurityCritical constructor. + /// + [SecurityCritical] + private BitmapHandle(bool ownsHandle) : base(ownsHandle, NativeMethods.CommonHandles.GDI) + { + } + /// + /// Critical: This calls into DeleteObject + /// + [SecurityCritical] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + protected override bool ReleaseHandle() + { + return UnsafeNativeMethods.DeleteObject(handle); + } + + /// + /// Critical: Accesses internal critical data. + /// + [SecurityCritical] + internal HandleRef MakeHandleRef(object obj) + { + return new HandleRef(obj, handle); + } + + /// + /// Critical: Creates a new BitmapHandle using Critical constructor. + /// + [SecurityCritical] + internal static BitmapHandle CreateFromHandle(IntPtr hbitmap, bool ownsHandle=true) + { + return new BitmapHandle(ownsHandle) + { + handle = hbitmap, + }; + } + } + + internal sealed class IconHandle : WpfSafeHandle + { + /// + /// Critical: This code calls into a base class which is protected by a SecurityCritical constructor. + /// + [SecurityCritical] + private IconHandle() : base(true, NativeMethods.CommonHandles.Icon) + { + } + + /// + /// Critical: This calls into DestroyIcon + /// + [SecurityCritical] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + protected override bool ReleaseHandle() + { + return UnsafeNativeMethods.DestroyIcon(handle); + } + + /// + /// Critical: This creates a new SafeHandle, which has a critical constructor. + /// TreatAsSafe: The handle this creates is invalid. It contains no critical data. + /// + [SecurityCritical, SecurityTreatAsSafe] + internal static IconHandle GetInvalidIcon() + { + return new IconHandle(); + } + + /// + /// Get access to the raw handle for native APIs that require it. + /// + /// + /// Critical: This accesses critical data for the safe handle. + /// + [SecurityCritical] + internal IntPtr CriticalGetHandle() + { + return handle; + } + } + + internal sealed class CursorHandle : WpfSafeHandle + { + /// + /// Critical: This code calls into a base class which is protected by a SecurityCritical constructor. + /// + [SecurityCritical] + private CursorHandle() : base(true, NativeMethods.CommonHandles.Cursor) + { + } + + /// + /// Critical: This calls into DestroyCursor + /// + [SecurityCritical] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + protected override bool ReleaseHandle() + { + return UnsafeNativeMethods.DestroyCursor( handle ); + } + + /// + /// Critical: This creates a new SafeHandle, which has a critical constructor. + /// TreatAsSafe: The handle this creates is invalid. It contains no critical data. + /// + [SecurityCritical, SecurityTreatAsSafe] + internal static CursorHandle GetInvalidCursor() + { + return new CursorHandle(); + } + } + + public static int SignedHIWORD(IntPtr intPtr) + { + return SignedHIWORD(IntPtrToInt32(intPtr)); + } + + public static int SignedLOWORD(IntPtr intPtr) + { + return SignedLOWORD(IntPtrToInt32(intPtr)); + } + + public const int SIZE_RESTORED = 0; + public const int SIZE_MINIMIZED = 1; + + public const int WS_EX_NOACTIVATE = 0x08000000; + public const int VK_LSHIFT = 0xA0; + public const int VK_RMENU = 0xA5; + public const int VK_LMENU = 0xA4; + public const int VK_LCONTROL = 0xA2; + public const int VK_RCONTROL = 0xA3; + public const int VK_LBUTTON = 0x01; + public const int VK_RBUTTON = 0x02; + public const int VK_MBUTTON = 0x04; + public const int VK_XBUTTON1 = 0x05; + public const int VK_XBUTTON2 = 0x06; + + // We have this wrapper because casting IntPtr to int may + // generate OverflowException when one of high 32 bits is set. + public static int IntPtrToInt32(IntPtr intPtr) + { + return unchecked((int)intPtr.ToInt64()); + } + + public const int PM_QS_SENDMESSAGE = unchecked(QS_SENDMESSAGE << 16); + public const int PM_QS_POSTMESSAGE = unchecked((QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER) << 16); + public const int MWMO_WAITALL = 0x0001; + public const int MWMO_ALERTABLE = 0x0002; + public const int MWMO_INPUTAVAILABLE = 0x0004; + + public static IntPtr HWND_MESSAGE = new IntPtr(-3); + + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + public class WNDCLASSEX_I + { + public int cbSize = 0; + + public int style = 0; + + public IntPtr lpfnWndProc = IntPtr.Zero; + + public int cbClsExtra = 0; + + public int cbWndExtra = 0; + + public IntPtr hInstance = IntPtr.Zero; + + public IntPtr hIcon = IntPtr.Zero; + + public IntPtr hCursor = IntPtr.Zero; + + public IntPtr hbrBackground = IntPtr.Zero; + + public IntPtr lpszMenuName = IntPtr.Zero; + + public IntPtr lpszClassName = IntPtr.Zero; + + public IntPtr hIconSm = IntPtr.Zero; + } + + // NOTE: this replaces the RECT struct in NativeMethodsCLR.cs because it adds an extra method IsEmpty + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int left; + public int top; + public int right; + public int bottom; + + public RECT(int left, int top, int right, int bottom) + { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } + + public int Width + { + get { return right - left; } + } + + public int Height + { + get { return bottom - top; } + } + + public void Offset(int dx, int dy) + { + left += dx; + top += dy; + right += dx; + bottom += dy; + } + + public bool IsEmpty + { + get + { + return left >= right || top >= bottom; + } + } + } + + // Provided for interop scenarios that require passing a NULL RECT*. + [StructLayout(LayoutKind.Sequential)] + internal class RefRECT + { + public int left; + public int top; + public int right; + public int bottom; + + public RefRECT() + {} + + public RefRECT(int left, int top, int right, int bottom) + { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } + + public int Width + { + get { return right - left; } + } + + public int Height + { + get { return bottom - top; } + } + + public void Offset(int dx, int dy) + { + left += dx; + top += dy; + right += dx; + bottom += dy; + } + + public bool IsEmpty + { + get + { + return left >= right || top >= bottom; + } + } + } + + // NOTE: this replaces the struct in NativeMethodsCLR.cs because it adds some additonal methods + [StructLayout(LayoutKind.Sequential, Pack = 2)] + public struct BITMAPINFO + { + // bmiHeader was a by-value BITMAPINFOHEADER structure + public int bmiHeader_biSize; // ndirect.DllLib.sizeOf( BITMAPINFOHEADER.class ); + + public int bmiHeader_biWidth; + + public int bmiHeader_biHeight; + + public short bmiHeader_biPlanes; + + public short bmiHeader_biBitCount; + + public int bmiHeader_biCompression; + + public int bmiHeader_biSizeImage; + + public int bmiHeader_biXPelsPerMeter; + + public int bmiHeader_biYPelsPerMeter; + + public int bmiHeader_biClrUsed; + + public int bmiHeader_biClrImportant; + + + // hamidm -- 03/08/2006 + // if the following RGBQUAD struct is added in this struct, + // we need to update bmiHeader_biSize in the cctor to hard-coded 40 + // since it expects the size of the BITMAPINFOHEADER only + // + // bmiColors was an embedded array of RGBQUAD structures + // public byte bmiColors_rgbBlue = 0; + // public byte bmiColors_rgbGreen = 0; + // public byte bmiColors_rgbRed = 0; + // public byte bmiColors_rgbReserved = 0; + public BITMAPINFO(int width, int height, short bpp) + { + bmiHeader_biSize = SizeOf(); + bmiHeader_biWidth = width; + bmiHeader_biHeight = height; + bmiHeader_biPlanes = 1; + bmiHeader_biBitCount = bpp; + bmiHeader_biCompression = 0; + bmiHeader_biSizeImage = 0; + bmiHeader_biXPelsPerMeter = 0; + bmiHeader_biYPelsPerMeter = 0; + bmiHeader_biClrUsed = 0; + bmiHeader_biClrImportant = 0; + } + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(BITMAPINFO)); + } + } + + [StructLayout(LayoutKind.Sequential)] + internal class SECURITY_ATTRIBUTES + { + /// + /// Critical : Initializes critical SafeHandle field + /// Safe : Initializes handle to known safe value + /// + [SecuritySafeCritical] + public SECURITY_ATTRIBUTES () + { + lpSecurityDescriptor = new SafeLocalMemHandle(); + } + + public int nLength = SizeOf(); + + /// + /// Critical : Exposes critical SafeHandle + /// + [SecurityCritical] + public SafeLocalMemHandle lpSecurityDescriptor = new SafeLocalMemHandle(); + + public bool bInheritHandle = false; + + /// + /// Critical : Disposes critical lpSecurityDescriptor field + /// + [SecurityCritical] + public void Release() + { + if (lpSecurityDescriptor != null) + { + lpSecurityDescriptor.Dispose(); + + // we do not set the handle to null because .Net marshaling will throw an exception if we pinvoke with a structure containing a null SafeHandle field + lpSecurityDescriptor = new SafeLocalMemHandle(); + } + } + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES)); + } + } + + /// + /// Critical: Inherits from critical tyoe SafeHandleZeroOrMinusOneIsInvalid + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort=true)] + internal sealed class SafeLocalMemHandle : SafeHandleZeroOrMinusOneIsInvalid + { + /// + /// Critical: Calls critical SafeHandle ctor + /// + [SecurityCritical] + public SafeLocalMemHandle() : base(true) + { + } + + /// + /// Critical: Calls critical SafeHandle.SetHandle + /// + [SecurityCritical] + public SafeLocalMemHandle(IntPtr existingHandle, bool ownsHandle) : base(ownsHandle) + { + base.SetHandle(existingHandle); + } + + /// + /// Critical: Calls critical LocalFree + /// + [SecurityCritical] + protected override bool ReleaseHandle() + { + return (LocalFree(base.handle) == IntPtr.Zero); + } + + /// + /// Critical: Elevates to unmanaged code permissions + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + [DllImport("kernel32.dll")] + private static extern IntPtr LocalFree(IntPtr hMem); + } + + + internal const uint DELETE = 0x00010000, READ_CONTROL = 0x00020000, WRITE_DAC = 0x00040000, WRITE_OWNER = 0x00080000, SYNCHRONIZE = 0x00100000, STANDARD_RIGHTS_REQUIRED = 0x000F0000, STANDARD_RIGHTS_READ = READ_CONTROL, STANDARD_RIGHTS_WRITE = READ_CONTROL, STANDARD_RIGHTS_EXECUTE = READ_CONTROL, STANDARD_RIGHTS_ALL = 0x001F0000, SPECIFIC_RIGHTS_ALL = 0x0000FFFF, ACCESS_SYSTEM_SECURITY = 0x01000000, MAXIMUM_ALLOWED = 0x02000000, GENERIC_READ = 0x80000000, GENERIC_WRITE = 0x40000000, GENERIC_EXECUTE = 0x20000000, GENERIC_ALL = 0x10000000; + + internal const uint FILE_READ_DATA = 0x0001, // file & pipe + FILE_LIST_DIRECTORY = 0x0001, // directory + FILE_WRITE_DATA = 0x0002, // file & pipe + FILE_ADD_FILE = 0x0002, // directory + FILE_APPEND_DATA = 0x0004, // file + FILE_ADD_SUBDIRECTORY = 0x0004, // directory + FILE_CREATE_PIPE_INSTANCE = 0x0004, // named pipe + FILE_READ_EA = 0x0008, // file & directory + FILE_WRITE_EA = 0x0010, // file & directory + FILE_EXECUTE = 0x0020, // file + FILE_TRAVERSE = 0x0020, // directory + FILE_DELETE_CHILD = 0x0040, // directory + FILE_READ_ATTRIBUTES = 0x0080, // all + FILE_WRITE_ATTRIBUTES = 0x0100; // all + + internal const uint FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF, FILE_GENERIC_READ = STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE, FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE, FILE_GENERIC_EXECUTE = STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE; + + internal const uint FILE_SHARE_READ = 0x00000001, FILE_SHARE_WRITE = 0x00000002, FILE_SHARE_DELETE = 0x00000004; + + internal const int ERROR_ALREADY_EXISTS = 183; + + internal const int OPEN_EXISTING = 3; + + internal const int PAGE_READONLY = 0x02; + + internal const int SECTION_MAP_READ = 0x0004; + + internal const int FILE_ATTRIBUTE_NORMAL = 0x00000080; + internal const int FILE_ATTRIBUTE_TEMPORARY = 0x00000100; + internal const int FILE_FLAG_DELETE_ON_CLOSE = 0x04000000; + + internal const int CREATE_ALWAYS = 2; + + internal const int PROCESS_ALL_ACCESS = (int)(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public class WNDCLASSEX_D + { + public int cbSize = 0; + + public int style = 0; + + public WndProc lpfnWndProc = null; + + public int cbClsExtra = 0; + + public int cbWndExtra = 0; + + public IntPtr hInstance = IntPtr.Zero; + + public IntPtr hIcon = IntPtr.Zero; + + public IntPtr hCursor = IntPtr.Zero; + + public IntPtr hbrBackground = IntPtr.Zero; + + public string lpszMenuName = null; + + public string lpszClassName = null; + + public IntPtr hIconSm = IntPtr.Zero; + } + + +#if BASE_NATIVEMETHODS + + public const int QS_EVENT = 0x2000; + + public const int VK_CANCEL = 0x03; + + + public const int VK_BACK = 0x08; + + public const int VK_CLEAR = 0x0C; + + public const int VK_RETURN = 0x0D; + + public const int VK_PAUSE = 0x13; + + public const int VK_CAPITAL = 0x14; + + public const int VK_KANA = 0x15; + + public const int VK_HANGEUL = 0x15; + + public const int VK_HANGUL = 0x15; + + public const int VK_JUNJA = 0x17; + + public const int VK_FINAL = 0x18; + + public const int VK_HANJA = 0x19; + + public const int VK_KANJI = 0x19; + + public const int VK_ESCAPE = 0x1B; + + public const int VK_CONVERT = 0x1C; + + public const int VK_NONCONVERT = 0x1D; + + public const int VK_ACCEPT = 0x1E; + + public const int VK_MODECHANGE = 0x1F; + + public const int VK_SPACE = 0x20; + + public const int VK_PRIOR = 0x21; + + public const int VK_NEXT = 0x22; + + public const int VK_END = 0x23; + + public const int VK_HOME = 0x24; + + public const int VK_LEFT = 0x25; + + public const int VK_UP = 0x26; + + public const int VK_RIGHT = 0x27; + + public const int VK_DOWN = 0x28; + + public const int VK_SELECT = 0x29; + + public const int VK_PRINT = 0x2A; + + public const int VK_EXECUTE = 0x2B; + + public const int VK_SNAPSHOT = 0x2C; + + public const int VK_INSERT = 0x2D; + + public const int VK_DELETE = 0x2E; + + public const int VK_HELP = 0x2F; + + public const int VK_0 = 0x30; + + public const int VK_1 = 0x31; + + public const int VK_2 = 0x32; + + public const int VK_3 = 0x33; + + public const int VK_4 = 0x34; + + public const int VK_5 = 0x35; + + public const int VK_6 = 0x36; + + public const int VK_7 = 0x37; + + public const int VK_8 = 0x38; + + public const int VK_9 = 0x39; + + public const int VK_A = 0x41; + + public const int VK_B = 0x42; + + public const int VK_C = 0x43; + + public const int VK_D = 0x44; + + public const int VK_E = 0x45; + + public const int VK_F = 0x46; + + public const int VK_G = 0x47; + + public const int VK_H = 0x48; + + public const int VK_I = 0x49; + + public const int VK_J = 0x4A; + + public const int VK_K = 0x4B; + + public const int VK_L = 0x4C; + + public const int VK_M = 0x4D; + + public const int VK_N = 0x4E; + + public const int VK_O = 0x4F; + + public const int VK_P = 0x50; + + public const int VK_Q = 0x51; + + public const int VK_R = 0x52; + + public const int VK_S = 0x53; + + public const int VK_T = 0x54; + + public const int VK_U = 0x55; + + public const int VK_V = 0x56; + + public const int VK_W = 0x57; + + public const int VK_X = 0x58; + + public const int VK_Y = 0x59; + + public const int VK_Z = 0x5A; + + public const int VK_LWIN = 0x5B; + + public const int VK_RWIN = 0x5C; + + public const int VK_APPS = 0x5D; + + public const int VK_POWER = 0x5E; + + public const int VK_SLEEP = 0x5F; + + public const int VK_NUMPAD0 = 0x60; + + public const int VK_NUMPAD1 = 0x61; + + public const int VK_NUMPAD2 = 0x62; + + public const int VK_NUMPAD3 = 0x63; + + public const int VK_NUMPAD4 = 0x64; + + public const int VK_NUMPAD5 = 0x65; + + public const int VK_NUMPAD6 = 0x66; + + public const int VK_NUMPAD7 = 0x67; + + public const int VK_NUMPAD8 = 0x68; + + public const int VK_NUMPAD9 = 0x69; + + public const int VK_MULTIPLY = 0x6A; + + public const int VK_ADD = 0x6B; + + public const int VK_SEPARATOR = 0x6C; + + public const int VK_SUBTRACT = 0x6D; + + public const int VK_DECIMAL = 0x6E; + + public const int VK_DIVIDE = 0x6F; + + public const int VK_F1 = 0x70; + + public const int VK_F2 = 0x71; + + public const int VK_F3 = 0x72; + + public const int VK_F4 = 0x73; + + public const int VK_F5 = 0x74; + + public const int VK_F6 = 0x75; + + public const int VK_F7 = 0x76; + + public const int VK_F8 = 0x77; + + public const int VK_F9 = 0x78; + + public const int VK_F10 = 0x79; + + public const int VK_F11 = 0x7A; + + public const int VK_F12 = 0x7B; + + public const int VK_F13 = 0x7C; + + public const int VK_F14 = 0x7D; + + public const int VK_F15 = 0x7E; + + public const int VK_F16 = 0x7F; + + public const int VK_F17 = 0x80; + + public const int VK_F18 = 0x81; + + public const int VK_F19 = 0x82; + + public const int VK_F20 = 0x83; + + public const int VK_F21 = 0x84; + + public const int VK_F22 = 0x85; + + public const int VK_F23 = 0x86; + + public const int VK_F24 = 0x87; + + public const int VK_NUMLOCK = 0x90; + + public const int VK_SCROLL = 0x91; + + + public const int VK_RSHIFT = 0xA1; + + public const int VK_BROWSER_BACK = 0xA6; + + public const int VK_BROWSER_FORWARD = 0xA7; + + public const int VK_BROWSER_REFRESH = 0xA8; + + public const int VK_BROWSER_STOP = 0xA9; + + public const int VK_BROWSER_SEARCH = 0xAA; + + public const int VK_BROWSER_FAVORITES = 0xAB; + + public const int VK_BROWSER_HOME = 0xAC; + + public const int VK_VOLUME_MUTE = 0xAD; + + public const int VK_VOLUME_DOWN = 0xAE; + + public const int VK_VOLUME_UP = 0xAF; + + public const int VK_MEDIA_NEXT_TRACK = 0xB0; + + public const int VK_MEDIA_PREV_TRACK = 0xB1; + + public const int VK_MEDIA_STOP = 0xB2; + + public const int VK_MEDIA_PLAY_PAUSE = 0xB3; + + public const int VK_LAUNCH_MAIL = 0xB4; + + public const int VK_LAUNCH_MEDIA_SELECT = 0xB5; + + public const int VK_LAUNCH_APP1 = 0xB6; + + public const int VK_LAUNCH_APP2 = 0xB7; + + public const int VK_PROCESSKEY = 0xE5; + + public const int VK_PACKET = 0xE7; + + public const int VK_ATTN = 0xF6; + + public const int VK_CRSEL = 0xF7; + + public const int VK_EXSEL = 0xF8; + + public const int VK_EREOF = 0xF9; + + public const int VK_PLAY = 0xFA; + + public const int VK_ZOOM = 0xFB; + + public const int VK_NONAME = 0xFC; + + public const int VK_PA1 = 0xFD; + + public const int VK_OEM_CLEAR = 0xFE; +#endif + + ///////////////////// + // from Framework + internal const int ENDSESSION_LOGOFF = (unchecked((int)0x80000000)); + + internal const int + ERROR_SUCCESS = 0; + + public const int LOCALE_FONTSIGNATURE = 0x00000058; + + public const int + SWP_NOREDRAW = 0x0008, + SWP_FRAMECHANGED = 0x0020, // The frame changed: send WM_NCCALCSIZE + SWP_NOCOPYBITS = 0x0100, + SWP_NOOWNERZORDER = 0x0200, // Don't do owner Z ordering + SWP_NOSENDCHANGING = 0x0400, // Don't send WM_WINDOWPOSCHANGING + SWP_NOREPOSITION = SWP_NOOWNERZORDER, + SWP_DEFERERASE = 0x2000, + SWP_ASYNCWINDOWPOS = 0x4000, + SPI_GETCURSORSHADOW = 0x101A, + SPI_SETCURSORSHADOW = 0x101B, + SPI_GETFOCUSBORDERWIDTH = 0x200E, + SPI_SETFOCUSBORDERWIDTH = 0x200F, + SPI_GETFOCUSBORDERHEIGHT = 0x2010, + SPI_SETFOCUSBORDERHEIGHT = 0x2011, + SPI_GETSTYLUSHOTTRACKING = 0x1010, + SPI_SETSTYLUSHOTTRACKING = 0x1011, + SPI_GETTOOLTIPFADE = 0x1018, + SPI_SETTOOLTIPFADE = 0x1019, + SPI_GETFOREGROUNDFLASHCOUNT = 0x2004, + SPI_SETFOREGROUNDFLASHCOUNT = 0x2005, + SPI_SETCARETWIDTH = 0x2007, + SPI_SETMOUSEVANISH = 0x1021, + SPI_SETHIGHCONTRAST = 0x0043, + SPI_SETKEYBOARDPREF = 0x0045, + SPI_SETFLATMENU = 0x1023, + SPI_SETDROPSHADOW = 0x1025, + SPI_SETWORKAREA = 0x002F, + SPI_SETICONMETRICS = 0x002E, + SPI_SETDRAGWIDTH = 0x004C, + SPI_SETDRAGHEIGHT = 0x004D, + SPI_SETPENWINDOWS = 0x0031, + SPI_SETMOUSEBUTTONSWAP = 0x0021, + SPI_SETSHOWSOUNDS = 0x0039, + SPI_SETKEYBOARDCUES = 0x100B, + SPI_SETKEYBOARDDELAY = 0x0017, + SPI_SETSNAPTODEFBUTTON = 0x0060, + SPI_SETWHEELSCROLLLINES = 0x0069, + SPI_SETMOUSEHOVERWIDTH = 0x0063, + SPI_SETMOUSEHOVERHEIGHT = 0x0065, + SPI_SETMOUSEHOVERTIME = 0x0067, + SPI_SETMENUDROPALIGNMENT = 0x001C, + SPI_SETMENUFADE = 0x1013, + SPI_SETMENUSHOWDELAY = 0x006B, + SPI_SETCOMBOBOXANIMATION = 0x1005, + SPI_SETCLIENTAREAANIMATION = 0x1043, + SPI_SETGRADIENTCAPTIONS = 0x1009, + SPI_SETHOTTRACKING = 0x100F, + SPI_SETLISTBOXSMOOTHSCROLLING = 0x1007, + SPI_SETMENUANIMATION = 0x1003, + SPI_SETSELECTIONFADE = 0x1015, + SPI_SETTOOLTIPANIMATION = 0x1017, + SPI_SETUIEFFECTS = 0x103F, + SPI_SETANIMATION = 0x0049, + SPI_SETDRAGFULLWINDOWS = 0x0025, + SPI_SETBORDER = 0x0006, + SPI_SETNONCLIENTMETRICS = 0x002A; + + public const int LANG_KOREAN = 0x12; + +#if NEVER + public static int PRIMARYLANGID(int lgid) + { + return ((ushort)(lgid) & 0x3ff); + } +#endif + + public const int + MB_YESNO = 0x00000004, + MB_SYSTEMMODAL = 0x00001000, + IDYES = 6; + + public const int PM_QS_INPUT = unchecked(QS_INPUT << 16); + public const int PM_QS_PAINT = unchecked(QS_PAINT << 16); + + + public const int + SW_PARENTCLOSING = 1, + SW_PARENTOPENING = 3, + SC_MOUSEMOVE = SC_MOVE + 0x02, + SPI_SETKEYBOARDSPEED = 0x000B; + + internal const int TYMED_HGLOBAL = 1; + internal const int TYMED_FILE = 2; + internal const int TYMED_ISTREAM = 4; + internal const int TYMED_ISTORAGE = 8; + internal const int TYMED_GDI = 16; + internal const int TYMED_MFPICT = 32; + internal const int TYMED_ENHMF = 64; + + + public const int WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX); + + public const int KEYEVENTF_EXTENDEDKEY = 0x0001; + public const int KEYEVENTF_KEYUP = 0x0002; + public const int KEYEVENTF_UNICODE = 0x0004; + public const int KEYEVENTF_SCANCODE = 0x0008; + + public const int MOUSEEVENTF_MOVE = 0x0001; + public const int MOUSEEVENTF_LEFTDOWN = 0x0002; + public const int MOUSEEVENTF_LEFTUP = 0x0004; + public const int MOUSEEVENTF_RIGHTDOWN = 0x0008; + public const int MOUSEEVENTF_RIGHTUP = 0x0010; + public const int MOUSEEVENTF_MIDDLEDOWN = 0x0020; + public const int MOUSEEVENTF_MIDDLEUP = 0x0040; + public const int MOUSEEVENTF_XDOWN = 0x0080; + public const int MOUSEEVENTF_XUP = 0x0100; + public const int MOUSEEVENTF_WHEEL = 0x00800; + public const int MOUSEEVENTF_VIRTUALDESK = 0x04000; + public const int MOUSEEVENTF_ABSOLUTE = 0x08000; + public const int MOUSEEVENTF_ACTUAL = 0x10000; + + public const int GWL_HINSTANCE = -6; + public const int GWL_USERDATA = -21; + public const int GCL_MENUNAME = -8; + public const int GCL_HBRBACKGROUND = -10; + public const int GCL_HCURSOR = -12; + public const int GCL_HICON = -14; + public const int GCL_HMODULE = -16; + public const int GCL_CBWNDEXTRA = -18; + public const int GCL_CBCLSEXTRA = -20; + public const int GCL_STYLE = -26; + public const int GCW_ATOM = -32; + public const int GCL_HICONSM = -34; + + public const int MONITOR_DEFAULTTONULL = 0x00000000; + public const int MONITOR_DEFAULTTOPRIMARY = 0x00000001; + public const int MONITOR_DEFAULTTONEAREST = 0x00000002; + + + [StructLayout(LayoutKind.Sequential)] + public class ANIMATIONINFO + { + public int cbSize = SizeOf(); + public int iMinAnimate = 0; + + /// + /// Critical : Calls critical Marshal.SizeOf + /// Safe : Calls method with trusted input (well known safe type) + /// + [SecuritySafeCritical] + private static int SizeOf() + { + return Marshal.SizeOf(typeof(ANIMATIONINFO)); + } + } + + + + [StructLayout(LayoutKind.Sequential)] + public sealed class STATDATA + { + [MarshalAs(UnmanagedType.U4)] + public int advf = 0; + [MarshalAs(UnmanagedType.U4)] + public int dwConnection = 0; + } + + public enum WINDOWTHEMEATTRIBUTETYPE + { + WTA_NONCLIENT = 1 + }; + + public const uint WTNCA_NODRAWCAPTION = 0x00000001; // don't draw the window caption + public const uint WTNCA_NODRAWICON = 0x00000002; // don't draw the system icon + public const uint WTNCA_NOSYSMENU = 0x00000004; // don't expose the system menu icon functionality + public const uint WTNCA_VALIDBITS = (WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON | WTNCA_NOSYSMENU); + +#if WCP_SYSTEM_THEMES_ENABLED + [StructLayout(LayoutKind.Sequential)] + public class WTA_OPTIONS + { + public uint dwFlags = 0; + public uint dwMask = 0; + }; +#endif // WCP_SYSTEM_THEMES_ENABLED + + + internal const int NO_ERROR = 0; + + + /////////////////////////// + // Used by BASE + + public const int VK_OEM_1 = 0xBA; + public const int VK_OEM_PLUS = 0xBB; + public const int VK_OEM_COMMA = 0xBC; + public const int VK_OEM_MINUS = 0xBD; + public const int VK_OEM_PERIOD = 0xBE; + public const int VK_OEM_2 = 0xBF; + public const int VK_OEM_3 = 0xC0; + public const int VK_C1 = 0xC1; // Brazilian ABNT_C1 key (not defined in winuser.h). + public const int VK_C2 = 0xC2; // Brazilian ABNT_C2 key (not defined in winuser.h). + public const int VK_OEM_4 = 0xDB; + public const int VK_OEM_5 = 0xDC; + public const int VK_OEM_6 = 0xDD; + public const int VK_OEM_7 = 0xDE; + public const int VK_OEM_8 = 0xDF; + public const int VK_OEM_AX = 0xE1; + public const int VK_OEM_102 = 0xE2; + public const int VK_OEM_RESET = 0xE9; + public const int VK_OEM_JUMP = 0xEA; + public const int VK_OEM_PA1 = 0xEB; + public const int VK_OEM_PA2 = 0xEC; + public const int VK_OEM_PA3 = 0xED; + public const int VK_OEM_WSCTRL = 0xEE; + public const int VK_OEM_CUSEL = 0xEF; + public const int VK_OEM_ATTN = 0xF0; + public const int VK_OEM_FINISH = 0xF1; + public const int VK_OEM_COPY = 0xF2; + public const int VK_OEM_AUTO = 0xF3; + public const int VK_OEM_ENLW = 0xF4; + public const int VK_OEM_BACKTAB = 0xF5; + + //////////////////////////// + // Needed by BASE +#if BASE_NATIVEMETHODS + /// + /// HWND. + /// + [StructLayout(LayoutKind.Sequential)] + public struct HWND + { + /// + /// + /// + public IntPtr h; + + /// + /// + /// + /// + /// + public static HWND Cast(IntPtr h) + { + HWND hTemp = new HWND(); + hTemp.h = h; + return hTemp; + } + + public HandleRef MakeHandleRef(object wrapper) + { + return new HandleRef(wrapper,h); + } + + /// + /// + /// + /// + /// + public static implicit operator IntPtr(HWND h) + { + return h.h; + } + + /// + /// + /// + /// + /// + /// + public static bool operator ==(HWND hl, HWND hr) + { + return (hl.h == hr.h); + } + + /// + /// + /// + /// + /// + /// + public static bool operator !=(HWND hl, HWND hr) + { + return (hl.h != hr.h); + } + + /// + /// + /// + /// + /// + override public bool Equals(object oCompare) + { + HWND hr = Cast((HWND)oCompare); + return (h == hr.h); + } + + /// + /// + /// + /// + public override int GetHashCode() + { + return (int)h; + } + } + + /// + /// HDC. + /// + public struct HDC + { + /// + /// + /// + public IntPtr h; + + /// + /// + /// + /// + /// + public static HDC Cast(IntPtr h) + { + HDC hTemp = new HDC(); + hTemp.h = h; + return hTemp; + } + + public HandleRef MakeHandleRef( object wrapper) + { + return new HandleRef(wrapper, h); + } + + /// + /// + /// + public static HDC NULL + { + get + { + HDC hTemp = new HDC(); + hTemp.h = IntPtr.Zero; + return hTemp; + } + } + } + + public const int DRAGDROP_S_DROP = 0x00040100; + public const int DRAGDROP_S_CANCEL = 0x00040101; + public const int DRAGDROP_S_USEDEFAULTCURSORS = 0x00040102; + + public const int TME_CANCEL = (unchecked((int)0x80000000)); + public const int IDC_HAND = 32649; + + /// + /// End document printing + /// + /// Printer DC + /// More than 0 if succeeds, zero or less if fails + /// + /// Critical: Elevates to unmanaged code permissions + /// + [SecurityCritical] + [DllImport("gdi32.dll")] + public static extern Int32 EndDoc(HDC hdc); + + public const int DM_ORIENTATION = 0x00000001; + public const int DM_PAPERSIZE = 0x00000002; + public const int DM_PAPERLENGTH = 0x00000004; + public const int DM_PAPERWIDTH = 0x00000008; + public const int DM_PRINTQUALITY = 0x00000400; + public const int DM_YRESOLUTION = 0x00002000; + + /// + /// Escape description for ExtEscape + /// + [StructLayout(LayoutKind.Sequential)] + public unsafe struct PrinterEscape + { + public Int32 cbInput; + public UInt32 cbOutput; + public UInt32 opcode; + public Int32 cbSize; + + /// + /// Critical: Exposes native pointer + /// + [SecurityCritical] + public void* buffer; + } + + /// + /// Send Escape to DC (printer) + /// + /// Printer DC + /// Escape code + /// # bytes in lpvInData + /// Input data + /// size of lpvOutData in bytes + /// Structure to receive data + /// 0 if escape not implemented, negative if error, otherwise succeeds + /// + /// Critical: Elevates to unmanaged code permissions + /// + [SecurityCritical] + [DllImport("gdi32.dll")] + public static unsafe extern Int32 ExtEscape(HDC hdc, Int32 nEscape, Int32 cbInput, PrinterEscape* lpvInData, Int32 cbOutput, [Out] void* lpvOutData); + + public const int MM_ISOTROPIC = 7; + + + public const int DM_OUT_BUFFER = 2; + + + /// + /// Document info for printing + /// + [StructLayout(LayoutKind.Sequential)] + public unsafe struct DocInfo + {// (*)indicates must be specfied + internal Int32 cbSize; // (*)size of this structure (20) + internal String lpszName; // (*)Name of document + internal String lpszOutput; // Name of output file (null) + internal String lpszDatatype; // Type of data ("raw" or "emf") can be null + internal Int32 fwType; // Flags about print job (0) + } + + /// + /// Start document printing + /// + /// Printer DC + /// Document information + /// More than zero if succeeded + /// + /// Critical: Elevates to unmanaged code permissions + /// + [SecurityCritical] + [DllImport("gdi32.dll")] + public unsafe static extern Int32 StartDoc(HDC hdc, ref DocInfo docInfo); + + /// + /// + /// + /// + /// + /// + /// + /// + /// Critical: Elevates to unmanaged code permissions + /// + [SecurityCritical] + [DllImport("winspool.drv", BestFitMapping = false, ThrowOnUnmappableChar = true)] + public unsafe static extern Int32 OpenPrinterA(String printerName, IntPtr* phPrinter, void* pDefaults); + + /// + /// + /// + /// + /// + /// + /// Critical: Elevates to unmanaged code permissions + /// + [SecurityCritical] + [DllImport("winspool.drv")]//CASRemoval: + public static extern Int32 ClosePrinter(IntPtr hPrinter); + + /// + /// End document page + /// + /// Printer DC + /// More than 0 if succeeds, zero or less if fails + /// + /// Critical: Elevates to unmanaged code permissions + /// + [SecurityCritical] + [DllImport("gdi32.dll")]//CASRemoval: + public static extern Int32 EndPage(HDC hdc); + + /// + /// Start document page + /// + /// Printer DC + /// More than 0 if succeeds, zero or less if fails + /// + /// Critical: Elevates to unmanaged code permissions + /// + [SecurityCritical] + [DllImport("gdi32.dll")]//CASRemoval: + public static extern Int32 StartPage(HDC hdc); + + /// Win32 constants + public const int E_HANDLE = unchecked((int)0x80070006); + + /// wParam for WM_SETTINGCHANGE + public const int SPI_SETFONTSMOOTHING = 0x004B; + /// wParam for WM_SETTINGCHANGE + public const int SPI_SETFONTSMOOTHINGTYPE = 0x200B; + /// wParam for WM_SETTINGCHANGE + public const int SPI_SETFONTSMOOTHINGCONTRAST = 0x200D; + /// wParam for WM_SETTINGCHANGE + public const int SPI_SETFONTSMOOTHINGORIENTATION = 0x2013; + /// wParam for WM_SETTINGCHANGE + public const int SPI_SETDISPLAYPIXELSTRUCTURE = 0x2015; + /// wParam for WM_SETTINGCHANGE + public const int SPI_SETDISPLAYGAMMA = 0x2017; + /// wParam for WM_SETTINGCHANGE + public const int SPI_SETDISPLAYCLEARTYPELEVEL = 0x2019; + /// wParam for WM_SETTINGCHANGE + public const int SPI_SETDISPLAYTEXTCONTRASTLEVEL = 0x201b; + + public const int GMMP_USE_DISPLAY_POINTS = 1; + public const int GMMP_USE_HIGH_RESOLUTION_POINTS = 2; + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] // For GetMouseMovePointsEx + public struct MOUSEMOVEPOINT { + public int x ; //Specifies the x-coordinate of the mouse + public int y ; //Specifies the x-coordinate of the mouse + public int time ; //Specifies the time stamp of the mouse coordinate + public IntPtr dwExtraInfo; //Specifies extra information associated with this coordinate. + } + + public const int ERROR_FILE_NOT_FOUND = 2; + public const int ERROR_PATH_NOT_FOUND = 3; + public const int ERROR_ACCESS_DENIED = 5; + public const int ERROR_INVALID_DRIVE = 15; + public const int ERROR_SHARING_VIOLATION = 32; + public const int ERROR_FILE_EXISTS = 80; + public const int ERROR_INVALID_PARAMETER = 87; + public const int ERROR_FILENAME_EXCED_RANGE = 206; + public const int ERROR_NO_MORE_ITEMS = 259; + public const int ERROR_OPERATION_ABORTED = 995; + +#endif // BASE_NATIVEMETHODS + + + public const int LR_DEFAULTCOLOR = 0x0000, + LR_MONOCHROME = 0x0001, + LR_COLOR = 0x0002, + LR_COPYRETURNORG = 0x0004, + LR_COPYDELETEORG = 0x0008, + LR_LOADFROMFILE = 0x0010, + LR_LOADTRANSPARENT = 0x0020, + LR_DEFAULTSIZE = 0x0040, + LR_VGACOLOR = 0x0080, + LR_LOADMAP3DCOLORS = 0x1000, + LR_CREATEDIBSECTION = 0x2000, + LR_COPYFROMRESOURCE = 0x4000, + LR_SHARED = unchecked((int)0x8000); + + internal enum Win32SystemColors + { + ActiveBorder = 0x0A, + ActiveCaption = 0x02, + ActiveCaptionText = 0x09, + AppWorkspace = 0x0C, + Control = 0x0F, + ControlDark = 0x10, + ControlDarkDark = 0x15, + ControlLight = 0x16, + ControlLightLight = 0x14, + ControlText = 0x12, + Desktop = 0x01, + GradientActiveCaption = 0x1B, + GradientInactiveCaption = 0x1C, + GrayText = 0x11, + Highlight = 0x0D, + HighlightText = 0x0E, + HotTrack = 0x1A, + InactiveBorder = 0x0B, + InactiveCaption = 0x03, + InactiveCaptionText = 0x13, + Info = 0x18, + InfoText = 0x17, + Menu = 0x04, + MenuBar = 0x1E, + MenuHighlight = 0x1D, + MenuText = 0x07, + ScrollBar = 0x00, + Window = 0x05, + WindowFrame = 0x06, + WindowText = 0x08 + } + +#if WINDOWS_BASE + // Copied from winineti.h + + // Note: CachePath should be an array of size 260. + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + internal struct InternetCacheConfigInfo + { + internal UInt32 dwStructSize; + internal UInt32 dwContainer; + internal UInt32 dwQuota; + internal UInt32 dwReserved4; + [MarshalAs(UnmanagedType.Bool)] internal bool fPerUser; + internal UInt32 dwSyncMode; + internal UInt32 dwNumCachePaths; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] internal string CachePath; + internal UInt32 dwCacheSize; + internal UInt32 dwNormalUsage; + internal UInt32 dwExemptUsage; + } +#endif + + public const int WTS_CONSOLE_CONNECT = 0x1; + public const int WTS_CONSOLE_DISCONNECT = 0x2; + public const int WTS_REMOTE_CONNECT = 0x3; + public const int WTS_REMOTE_DISCONNECT = 0x4; + public const int WTS_SESSION_LOCK = 0x7; + public const int WTS_SESSION_UNLOCK = 0x8; + + public const uint NOTIFY_FOR_THIS_SESSION = 0; + + public const int PBT_APMSUSPEND = 0x0004; + public const int PBT_APMRESUMECRITICAL = 0x0006; + public const int PBT_APMRESUMESUSPEND = 0x0007; + public const int PBT_APMRESUMEAUTOMATIC = 0x0012; + public const int PBT_POWERSETTINGCHANGE = 0x8013; + + [StructLayout(LayoutKind.Sequential, Pack = 4)] + public struct POWERBROADCAST_SETTING { + public Guid PowerSetting; + public int DataLength; + public byte Data; + } + + public static readonly Guid GUID_MONITOR_POWER_ON = new Guid(0x02731015, 0x4510, 0x4526, 0x99, 0xE6, 0xE5, 0xA1, 0x7E, 0xBD, 0x1A, 0xEA); + + + + public const uint PROFILE_READ = 1; + + // + // + // + + public enum ProfileType : uint + { + PROFILE_FILENAME = 1, + PROFILE_MEMBUFFER = 2 + }; + + public enum COLORTYPE : uint + { + COLOR_GRAY = 1, + COLOR_RGB, + COLOR_XYZ, + COLOR_Yxy, + COLOR_Lab, + COLOR_3_CHANNEL, + COLOR_CMYK, + COLOR_5_CHANNEL, + COLOR_6_CHANNEL, + COLOR_7_CHANNEL, + COLOR_8_CHANNEL, + COLOR_NAMED, + + // Not part of the real enum in icm.h but here for backwards compat + COLOR_UNDEFINED = 255 + }; + + public enum ColorSpace : uint + { + SPACE_XYZ = 0x58595A20, // = 'XYZ ' + SPACE_Lab = 0x4C616220, // = 'Lab ' + SPACE_Luv = 0x4C757620, // = 'Luv ' + SPACE_YCbCr = 0x59436272, // = 'YCbr' + SPACE_Yxy = 0x59787920, // = 'Yxy ' + SPACE_RGB = 0x52474220, // = 'RGB ' + SPACE_GRAY = 0x47524159, // = 'GRAY' + SPACE_HSV = 0x48535620, // = 'HSV ' + SPACE_HLS = 0x484C5320, // = 'HLS ' + SPACE_CMYK = 0x434D594B, // = 'CMYK' + SPACE_CMY = 0x434D5920, // = 'CMY ' + SPACE_2_CHANNEL = 0x32434C52, // = '2CLR' + SPACE_3_CHANNEL = 0x33434C52, // = '3CLR' + SPACE_4_CHANNEL = 0x34434C52, // = '4CLR' + SPACE_5_CHANNEL = 0x35434C52, // = '5CLR' + SPACE_6_CHANNEL = 0x36434C52, // = '6CLR' + SPACE_7_CHANNEL = 0x37434C52, // = '7CLR' + SPACE_8_CHANNEL = 0x38434C52, // = '8CLR' + + // These are not in icm.h but were present in our original + // implementation. We don't know if these actually exist + // but we're going to leave them anyway for compat. + SPACE_9_CHANNEL = 0x39434C52, // = '9CLR' + SPACE_A_CHANNEL = 0x41434C52, // = 'ACLR' + SPACE_B_CHANNEL = 0x42434C52, // = 'BCLR' + SPACE_C_CHANNEL = 0x43434C52, // = 'CCLR' + SPACE_D_CHANNEL = 0x44434C52, // = 'DCLR' + SPACE_E_CHANNEL = 0x45434C52, // = 'ECLR' + SPACE_F_CHANNEL = 0x46434C52, // = 'FCLR' + SPACE_sRGB = 0x73524742 // = 'sRGB' + }; + + // + // + // + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsSetLastError.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsSetLastError.cs new file mode 100644 index 00000000000..c5442c27ac6 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsSetLastError.cs @@ -0,0 +1,176 @@ +//--------------------------------------------------------------------------- +// +// +// Copyright (C) Microsoft Corporation. All rights reserved. +// +// +// +// Description: P/Invokes for methods that need to call SetLastError(0) +// +//--------------------------------------------------------------------------- + +// The NativeMethodsSetLastError class differs between assemblies and could not actually be +// shared, so it is duplicated across namespaces to prevent name collision. +#if WINDOWS_BASE +namespace MS.Internal.WindowsBase +#elif UIAUTOMATIONCLIENT +namespace MS.Internal.UIAutomationClient +#elif UIAUTOMATIONCLIENTSIDEPROVIDERS +namespace MS.Internal.UIAutomationClientSideProviders +#elif WINDOWSFORMSINTEGRATION +namespace MS.Internal.WinFormsIntegration +#elif UIAUTOMATIONTYPES +namespace MS.Internal.UIAutomationTypes +#elif DRT +namespace MS.Internal.Drt +#else +#error Class is being used from an unknown assembly. +#endif +{ + using System; + using System.Diagnostics.CodeAnalysis; + using System.IO; + using System.Security; + using System.Security.Permissions; + using System.Runtime.InteropServices; + using System.Text; + using System.Windows; + using MS.Win32; + + [SuppressUnmanagedCodeSecurity, SecurityCritical(SecurityCriticalScope.Everything)] + internal static class NativeMethodsSetLastError + { + private const string PresentationNativeDll = "PresentationNative_cor3.dll"; + +#if WINDOWSFORMSINTEGRATION // WinFormsIntegration + + [SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")] + [DllImport(PresentationNativeDll, EntryPoint="EnableWindowWrapper", SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool EnableWindow(IntPtr hWnd, bool enable); + +#elif UIAUTOMATIONCLIENT || UIAUTOMATIONCLIENTSIDEPROVIDERS // UIAutomation + + [SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")] + [DllImport(PresentationNativeDll, EntryPoint="GetWindowLongWrapper", CharSet=CharSet.Auto, SetLastError=true)] + public static extern Int32 GetWindowLong(IntPtr hWnd, int nIndex ); + + [SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")] + [DllImport(PresentationNativeDll, EntryPoint="GetWindowLongPtrWrapper", CharSet=CharSet.Auto, SetLastError=true)] + public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex ); + + [DllImport(PresentationNativeDll, EntryPoint="GlobalDeleteAtomWrapper", ExactSpelling = true, SetLastError = true)] + public static extern short GlobalDeleteAtom(short atom); + +#if UIAUTOMATIONCLIENT // UIAutomationClient + + [DllImport(PresentationNativeDll, EntryPoint="GetMenuBarInfoWrapper", SetLastError = true)] + public static extern bool GetMenuBarInfo (IntPtr hwnd, int idObject, uint idItem, ref UnsafeNativeMethods.MENUBARINFO mbi); + + [DllImport(PresentationNativeDll, EntryPoint="GetWindowWrapper", ExactSpelling = true, SetLastError = true)] + public static extern NativeMethods.HWND GetWindow(NativeMethods.HWND hWnd, int uCmd); + + [DllImport(PresentationNativeDll, EntryPoint="MapWindowPointsWrapper", SetLastError = true, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern int MapWindowPoints(NativeMethods.HWND hWndFrom, NativeMethods.HWND hWndTo, [In, Out] ref NativeMethods.RECT rect, int cPoints); + + [DllImport(PresentationNativeDll, EntryPoint="MapWindowPointsWrapper", SetLastError = true, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern int MapWindowPoints(NativeMethods.HWND hWndFrom, NativeMethods.HWND hWndTo, [In, Out] ref NativeMethods.POINT pt, int cPoints); + +#elif UIAUTOMATIONCLIENTSIDEPROVIDERS // UIAutomationClientSideProviders + + [DllImport(PresentationNativeDll, EntryPoint="GetAncestorWrapper", CharSet = CharSet.Auto)] + public static extern IntPtr GetAncestor(IntPtr hwnd, int gaFlags); + + [DllImport(PresentationNativeDll, EntryPoint="FindWindowExWrapper", CharSet = CharSet.Unicode, SetLastError = true)] + public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string className, string wndName); + + [DllImport(PresentationNativeDll, EntryPoint="GetMenuBarInfoWrapper", SetLastError = true)] + public static extern bool GetMenuBarInfo (IntPtr hwnd, int idObject, uint idItem, ref NativeMethods.MENUBARINFO mbi); + + [DllImport(PresentationNativeDll, EntryPoint="GetTextExtentPoint32Wrapper", SetLastError = true)] + public static extern int GetTextExtentPoint32(IntPtr hdc, [MarshalAs(UnmanagedType.LPWStr)]string lpString, int cbString, out NativeMethods.SIZE lpSize); + + [DllImport(PresentationNativeDll, EntryPoint="GetWindowWrapper", ExactSpelling = true, SetLastError = true)] + public static extern IntPtr GetWindow(IntPtr hWnd, int uCmd); + + [DllImport(PresentationNativeDll, EntryPoint = "GetWindowTextWrapper", CharSet=CharSet.Auto, BestFitMapping = false, SetLastError = true)] + public static extern int GetWindowText(IntPtr hWnd, [Out] StringBuilder lpString, int nMaxCount); + + [DllImport(PresentationNativeDll, EntryPoint="MapWindowPointsWrapper", ExactSpelling = true, SetLastError = true)] + public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref NativeMethods.Win32Rect rect, int cPoints); + + [DllImport(PresentationNativeDll, EntryPoint="MapWindowPointsWrapper", ExactSpelling = true, SetLastError = true)] + public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] ref NativeMethods.Win32Point pt, int cPoints); + + [DllImport(PresentationNativeDll, EntryPoint="SetScrollPosWrapper", SetLastError = true)] + public static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw); + +#endif +#else // Base/Core/FW + DRT + + [DllImport(PresentationNativeDll, EntryPoint="EnableWindowWrapper", SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool EnableWindow(HandleRef hWnd, bool enable); + + [DllImport(PresentationNativeDll, EntryPoint="GetAncestorWrapper", CharSet = CharSet.Auto)] + public static extern IntPtr GetAncestor(IntPtr hwnd, int gaFlags); + + [DllImport(PresentationNativeDll, EntryPoint="GetKeyboardLayoutListWrapper", SetLastError = true, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern int GetKeyboardLayoutList(int size, [Out, MarshalAs(UnmanagedType.LPArray)] IntPtr[] hkls); + + [DllImport(PresentationNativeDll, EntryPoint="GetParentWrapper", SetLastError = true)] + public static extern IntPtr GetParent(HandleRef hWnd); + + [DllImport(PresentationNativeDll, EntryPoint="GetWindowWrapper", ExactSpelling = true, SetLastError = true)] + public static extern IntPtr GetWindow(IntPtr hWnd, int uCmd); + + [DllImport(PresentationNativeDll, EntryPoint="GetWindowLongWrapper", CharSet=CharSet.Auto, SetLastError=true)] + public static extern Int32 GetWindowLong(HandleRef hWnd, int nIndex ); + + [DllImport(PresentationNativeDll, EntryPoint="GetWindowLongWrapper", CharSet=CharSet.Auto, SetLastError=true)] + public static extern Int32 GetWindowLong(IntPtr hWnd, int nIndex ); + + [DllImport(PresentationNativeDll, EntryPoint="GetWindowLongWrapper", CharSet=CharSet.Auto, SetLastError=true)] + public static extern NativeMethods.WndProc GetWindowLongWndProc(HandleRef hWnd, int nIndex); + + [DllImport(PresentationNativeDll, EntryPoint="GetWindowLongPtrWrapper", CharSet=CharSet.Auto, SetLastError=true)] + public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex); + + [DllImport(PresentationNativeDll, EntryPoint="GetWindowLongPtrWrapper", CharSet=CharSet.Auto, SetLastError=true)] + public static extern IntPtr GetWindowLongPtr(HandleRef hWnd, int nIndex); + + [DllImport(PresentationNativeDll, EntryPoint="GetWindowLongPtrWrapper", CharSet=CharSet.Auto, SetLastError=true)] + public static extern NativeMethods.WndProc GetWindowLongPtrWndProc(HandleRef hWnd, int nIndex); + + [DllImport(PresentationNativeDll, EntryPoint = "GetWindowTextWrapper", CharSet=CharSet.Auto, BestFitMapping = false, SetLastError = true)] + public static extern int GetWindowText(HandleRef hWnd, [Out] StringBuilder lpString, int nMaxCount); + + [DllImport(PresentationNativeDll, EntryPoint = "GetWindowTextLengthWrapper", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] + public static extern int GetWindowTextLength(HandleRef hWnd); + + [DllImport(PresentationNativeDll, EntryPoint="MapWindowPointsWrapper", SetLastError = true, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern int MapWindowPoints(HandleRef hWndFrom, HandleRef hWndTo, [In, Out] ref NativeMethods.RECT rect, int cPoints); + + [DllImport(PresentationNativeDll, EntryPoint="SetFocusWrapper", SetLastError = true)] + public static extern IntPtr SetFocus(HandleRef hWnd); + + [DllImport(PresentationNativeDll, EntryPoint="SetWindowLongWrapper", CharSet=CharSet.Auto)] + public static extern Int32 SetWindowLong(HandleRef hWnd, int nIndex, Int32 dwNewLong); + + [DllImport(PresentationNativeDll, EntryPoint="SetWindowLongWrapper", CharSet=CharSet.Auto)] + public static extern Int32 SetWindowLong(IntPtr hWnd, int nIndex, Int32 dwNewLong); + + [DllImport(PresentationNativeDll, EntryPoint="SetWindowLongWrapper", CharSet=CharSet.Auto, SetLastError=true)] + public static extern Int32 SetWindowLongWndProc(HandleRef hWnd, int nIndex, NativeMethods.WndProc dwNewLong); + + [DllImport(PresentationNativeDll, EntryPoint="SetWindowLongPtrWrapper", CharSet=CharSet.Auto)] + public static extern IntPtr SetWindowLongPtr(HandleRef hWnd, int nIndex, IntPtr dwNewLong); + + [DllImport(PresentationNativeDll, EntryPoint="SetWindowLongPtrWrapper", CharSet=CharSet.Auto)] + public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong); + + [DllImport(PresentationNativeDll, EntryPoint="SetWindowLongPtrWrapper", CharSet=CharSet.Auto, SetLastError=true)] + public static extern IntPtr SetWindowLongPtrWndProc(HandleRef hWnd, int nIndex, NativeMethods.WndProc dwNewLong); + +#endif + + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/SafeNativeMethodsCLR.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/SafeNativeMethodsCLR.cs new file mode 100644 index 00000000000..53b08b90799 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/SafeNativeMethodsCLR.cs @@ -0,0 +1,681 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +namespace MS.Win32 +{ + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.ComTypes; + using System; + using System.Security; + using System.Security.Permissions; + using System.Collections; + using System.IO; + using System.Text; + using System.ComponentModel; + + +// The SecurityHelper class differs between assemblies and could not actually be +// shared, so it is duplicated across namespaces to prevent name collision. +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif DRT + using MS.Internal.Drt; +#else +#error Attempt to use a class (duplicated across multiple namespaces) from an unknown assembly. +#endif + + using IComDataObject = System.Runtime.InteropServices.ComTypes.IDataObject; + + /// + /// Critical - This entire class is critical as it has SuppressUnmanagedCodeSecurity. + /// TreatAsSafe - These Native methods have been reviewed as safe to call. + /// + internal static partial class SafeNativeMethods + { + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical, SecurityTreatAsSafe] + public static int GetMessagePos() + { + return SafeNativeMethodsPrivate.GetMessagePos(); + } + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical,SecurityTreatAsSafe] + public static IntPtr GetKeyboardLayout(int dwLayout) + { + return SafeNativeMethodsPrivate.GetKeyboardLayout(dwLayout); + } + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical,SecurityTreatAsSafe] + public static IntPtr ActivateKeyboardLayout(HandleRef hkl, int uFlags) + { + return SafeNativeMethodsPrivate.ActivateKeyboardLayout(hkl, uFlags); + } + +#if BASE_NATIVEMETHODS + /// + /// Critical - access unmanaged code via SetLastError() and IntGetKeyboardLayoutList(). + /// TreatAsSafe - no returns from SetLastError(). Calling IntGetKeyboardLayoutList() is safe. + /// + [SecurityCritical,SecurityTreatAsSafe] + public static int GetKeyboardLayoutList(int size, [Out, MarshalAs(UnmanagedType.LPArray)] IntPtr[] hkls) + { + int result = NativeMethodsSetLastError.GetKeyboardLayoutList(size, hkls); + if(result == 0) + { + int win32Err = Marshal.GetLastWin32Error(); + if (win32Err != 0) + { + throw new Win32Exception(win32Err); + } + } + + return result; + } +#endif + + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical,SecurityTreatAsSafe] + internal static void GetMonitorInfo(HandleRef hmonitor, [In, Out]NativeMethods.MONITORINFOEX info) + { + if (SafeNativeMethodsPrivate.IntGetMonitorInfo(hmonitor, info) == false) + { + throw new Win32Exception(); + } + } + + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical,SecurityTreatAsSafe] + public static IntPtr MonitorFromPoint(NativeMethods.POINTSTRUCT pt, int flags) + { + return SafeNativeMethodsPrivate.MonitorFromPoint(pt,flags); + } + + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical,SecurityTreatAsSafe] + public static IntPtr MonitorFromRect(ref NativeMethods.RECT rect, int flags) + { + return SafeNativeMethodsPrivate.MonitorFromRect(ref rect,flags); + } + + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical,SecurityTreatAsSafe] + public static IntPtr MonitorFromWindow(HandleRef handle, int flags) + { + return SafeNativeMethodsPrivate.MonitorFromWindow(handle, flags); + } + +#if BASE_NATIVEMETHODS + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical,SecurityTreatAsSafe] + public static NativeMethods.CursorHandle LoadCursor(HandleRef hInst, IntPtr iconId) + { + NativeMethods.CursorHandle cursorHandle = SafeNativeMethodsPrivate.LoadCursor(hInst, iconId); + if(cursorHandle == null || cursorHandle.IsInvalid) + { + throw new Win32Exception(); + } + + return cursorHandle; + } + +#endif + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical,SecurityTreatAsSafe] + public static IntPtr GetCursor() + { + return SafeNativeMethodsPrivate.GetCursor(); + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: Hiding cursor is ok + /// + [SecurityCritical, SecurityTreatAsSafe] + public static int ShowCursor(bool show) + { + return SafeNativeMethodsPrivate.ShowCursor(show); + } + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical, SecurityTreatAsSafe] + internal static bool AdjustWindowRectEx(ref NativeMethods.RECT lpRect, int dwStyle, bool bMenu, int dwExStyle) + { + bool returnValue = SafeNativeMethodsPrivate.IntAdjustWindowRectEx(ref lpRect, dwStyle, bMenu, dwExStyle); + if (returnValue == false) + { + throw new Win32Exception(); + } + return returnValue; + } + + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical,SecurityTreatAsSafe] + internal static void GetClientRect(HandleRef hWnd, [In, Out] ref NativeMethods.RECT rect) + { + if(!SafeNativeMethodsPrivate.IntGetClientRect(hWnd, ref rect)) + { + throw new Win32Exception(); + } + } + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical,SecurityTreatAsSafe] + internal static void GetWindowRect(HandleRef hWnd, [In, Out] ref NativeMethods.RECT rect) + { + if(!SafeNativeMethodsPrivate.IntGetWindowRect(hWnd, ref rect)) + { + throw new Win32Exception(); + } + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static int GetDoubleClickTime() + { + return SafeNativeMethodsPrivate.GetDoubleClickTime(); + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsafe: This function is safe to call + /// + [SecurityCritical, SecurityTreatAsSafe] + public static bool IsWindowEnabled(HandleRef hWnd) + { + return SafeNativeMethodsPrivate.IsWindowEnabled(hWnd); + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsafe: This function is safe to call + /// + [SecurityCritical, SecurityTreatAsSafe] + public static bool IsWindowVisible(HandleRef hWnd) + { + return SafeNativeMethodsPrivate.IsWindowVisible(hWnd); + } + + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical,SecurityTreatAsSafe] + internal static bool ReleaseCapture() + { + bool returnValue = SafeNativeMethodsPrivate.IntReleaseCapture(); + + if (returnValue == false) + { + throw new Win32Exception(); + } + return returnValue; + } + + +#if BASE_NATIVEMETHODS + /// + /// Critical: This code calls into unmanaged code which elevates + /// TreatAsSafe: This method is ok to give out + /// + [SecurityCritical,SecurityTreatAsSafe] + public static bool TrackMouseEvent(NativeMethods.TRACKMOUSEEVENT tme) + { + bool retVal = SafeNativeMethodsPrivate.TrackMouseEvent(tme); + int win32Err = Marshal.GetLastWin32Error(); // Dance around FxCop + if(!retVal && win32Err != 0) + { + throw new System.ComponentModel.Win32Exception(win32Err); + } + return retVal; + } + + + // Note: this overload has no return value. If we need an overload that + // returns the timer ID, then we'll need to add one. + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static void SetTimer(HandleRef hWnd, int nIDEvent, int uElapse) + { + if(SafeNativeMethodsPrivate.SetTimer(hWnd, nIDEvent, uElapse, null) == IntPtr.Zero) + { + throw new Win32Exception(); + } + } + + // Note: this returns true or false for success. We still don't have an overload + // that returns the timer ID. + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static bool TrySetTimer(HandleRef hWnd, int nIDEvent, int uElapse) + { + if(SafeNativeMethodsPrivate.TrySetTimer(hWnd, nIDEvent, uElapse, null) == IntPtr.Zero) + { + return false; + } + + return true; + } +#endif + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsafe: This function is safe to call as in the worst case it destroys the dispatcher timer. + /// it destroys a timer + /// + [SecurityCritical,SecurityTreatAsSafe] + public static bool KillTimer(HandleRef hwnd, int idEvent) + { + return (SafeNativeMethodsPrivate.KillTimer(hwnd,idEvent)); + } + + +#if FRAMEWORK_NATIVEMETHODS || CORE_NATIVEMETHODS || BASE_NATIVEMETHODS + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static int GetTickCount() + { + return SafeNativeMethodsPrivate.GetTickCount(); + } +#endif + +#if BASE_NATIVEMETHODS + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsafe: It is considered safe to play sounds. + /// + [SecurityCritical,SecurityTreatAsSafe] + public static int MessageBeep(int uType) + { + return SafeNativeMethodsPrivate.MessageBeep(uType); + } +#endif + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static bool IsWindowUnicode(HandleRef hWnd) + { + return (SafeNativeMethodsPrivate.IsWindowUnicode(hWnd)); + } + + +#if BASE_NATIVEMETHODS + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: Setting Cursor is ok + /// + [SecurityCritical,SecurityTreatAsSafe] + public static IntPtr SetCursor(HandleRef hcursor) + { + return SafeNativeMethodsPrivate.SetCursor(hcursor); + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: Setting Cursor is ok + /// + [SecurityCritical,SecurityTreatAsSafe] + public static IntPtr SetCursor(SafeHandle hcursor) + { + return SafeNativeMethodsPrivate.SetCursor(hcursor); + } +#endif + + // not used by compiler - don't include. + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: Screen to Clien is ok to give out + /// + [SecurityCritical, SecurityTreatAsSafe] + public static void ScreenToClient(HandleRef hWnd, [In, Out] NativeMethods.POINT pt) + { + if(SafeNativeMethodsPrivate.IntScreenToClient(hWnd, pt) == 0) + { + throw new Win32Exception(); + } + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: Process Id is ok to give out + /// + [SecurityCritical, SecurityTreatAsSafe] + public static int GetCurrentProcessId() + { + return SafeNativeMethodsPrivate.GetCurrentProcessId(); + } + + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: Thread ID is ok to give out + /// + [SecurityCritical, SecurityTreatAsSafe] + public static int GetCurrentThreadId() + { + return SafeNativeMethodsPrivate.GetCurrentThreadId(); + } + + /// + /// Returns the ID of the session under which the current process is running + /// + /// + /// safe: exposes non-critical information + /// critical: This code eleveates to unmanaged code permission + /// + /// + /// The session id upon success, null on failure + /// + [SecuritySafeCritical] + public static int? GetCurrentSessionId() + { + int? result = null; + + int sessionId; + if (SafeNativeMethodsPrivate.ProcessIdToSessionId( + GetCurrentProcessId(), out sessionId)) + { + result = sessionId; + } + + return result; + } + + /// + /// This will return a valid handle only if a window on the current thread has capture + /// else it will return NULL. (Refer to Platform SDK) + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: Getting mouse capture is ok + /// + [SecurityCritical, SecurityTreatAsSafe] + public static IntPtr GetCapture() + { + return SafeNativeMethodsPrivate.GetCapture(); + + } +#if BASE_NATIVEMETHODS + /// + /// This function cannot be used to capture mouse input for another process. + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: Setting Capture is ok + /// + [SecurityCritical, SecurityTreatAsSafe] + public static IntPtr SetCapture(HandleRef hwnd) + { + return SafeNativeMethodsPrivate.SetCapture(hwnd); + } + + /// + /// This can be guessed anyways and does not relay any risky information + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: Getting virtual key mapping is ok + /// + [SecurityCritical, SecurityTreatAsSafe] + internal static int MapVirtualKey(int nVirtKey, int nMapType) + { + return SafeNativeMethodsPrivate.MapVirtualKey(nVirtKey,nMapType); + } +#endif + + /// + /// Identifies whether the given workstation session ID has a WTSConnectState value + /// of WTSActive, or not. + /// + /// + /// The ID of the workstation session to query. If this is null, + /// then this will default to WTS_CURRENT_SESSION. Note that the ID of the + /// current session will not be queried explicitly. + /// + /// + /// The default result to return if this method is unable to identify the connection + /// state of the given session ID. + /// + /// + /// True if the connection state for is WTSActive; + /// false otherwise + /// is returned if WTSQuerySessionInformation + /// fails. + /// + /// + /// critical: This method elevates to unmanaged-code permission + /// safe: Returns safe information + /// + [SecuritySafeCritical] + public static bool IsCurrentSessionConnectStateWTSActive(int? SessionId = null, bool defaultResult = true) + { + IntPtr buffer = IntPtr.Zero; + int bytesReturned; + + int sessionId = SessionId.HasValue ? SessionId.Value : NativeMethods.WTS_CURRENT_SESSION; + bool currentSessionConnectState = defaultResult; + + try + { + if (SafeNativeMethodsPrivate.WTSQuerySessionInformation( + NativeMethods.WTS_CURRENT_SERVER_HANDLE, + sessionId, + NativeMethods.WTS_INFO_CLASS.WTSConnectState, + out buffer, out bytesReturned) && (bytesReturned >= sizeof(int))) + { + var data = Marshal.ReadInt32(buffer); + if (Enum.IsDefined(typeof(NativeMethods.WTS_CONNECTSTATE_CLASS), data)) + { + var connectState = (NativeMethods.WTS_CONNECTSTATE_CLASS)data; + currentSessionConnectState = (connectState == NativeMethods.WTS_CONNECTSTATE_CLASS.WTSActive); + } + } + } + finally + { + try + { + if (buffer != IntPtr.Zero) + { + SafeNativeMethodsPrivate.WTSFreeMemory(buffer); + } + } + catch (Exception e) when (e is Win32Exception || e is SEHException) + { + // We will do nothing and return defaultResult + // + // Note that we don't want to catch and ignore SystemException types + // like AV, OOM etc. + } + } + + return currentSessionConnectState; + } + + [SuppressUnmanagedCodeSecurity,SecurityCritical(SecurityCriticalScope.Everything)] + private partial class SafeNativeMethodsPrivate + { + + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern int GetCurrentProcessId(); + + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Auto)] + [return:MarshalAs(UnmanagedType.Bool)] + public static extern bool ProcessIdToSessionId([In]int dwProcessId, [Out]out int pSessionId); + + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern int GetCurrentThreadId(); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern IntPtr GetCapture(); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool IsWindowVisible(HandleRef hWnd); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern int GetMessagePos(); + + [DllImport(ExternDll.User32, EntryPoint = "ReleaseCapture", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] + public static extern bool IntReleaseCapture(); + + [DllImport(ExternDll.User32, EntryPoint = "GetWindowRect", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool IntGetWindowRect(HandleRef hWnd, [In, Out] ref NativeMethods.RECT rect); + + [DllImport(ExternDll.User32, EntryPoint = "GetClientRect", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool IntGetClientRect(HandleRef hWnd, [In, Out] ref NativeMethods.RECT rect); + + [DllImport(ExternDll.User32, EntryPoint = "AdjustWindowRectEx", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] + public static extern bool IntAdjustWindowRectEx(ref NativeMethods.RECT lpRect, int dwStyle, bool bMenu, int dwExStyle); + + [DllImport(ExternDll.User32, ExactSpelling=true)] + public static extern IntPtr MonitorFromRect(ref NativeMethods.RECT rect, int flags); + + [DllImport(ExternDll.User32, ExactSpelling = true)] + public static extern IntPtr MonitorFromPoint(NativeMethods.POINTSTRUCT pt, int flags); + + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern IntPtr ActivateKeyboardLayout(HandleRef hkl, int uFlags); + + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern IntPtr GetKeyboardLayout(int dwLayout); + + [DllImport(ExternDll.User32, SetLastError = true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + public static extern IntPtr SetTimer(HandleRef hWnd, int nIDEvent, int uElapse, NativeMethods.TimerProc lpTimerFunc); + + [DllImport(ExternDll.User32, EntryPoint="SetTimer", CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern IntPtr TrySetTimer(HandleRef hWnd, int nIDEvent, int uElapse, NativeMethods.TimerProc lpTimerFunc); + + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool KillTimer(HandleRef hwnd, int idEvent); + + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool IsWindowUnicode(HandleRef hWnd); + + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern int GetDoubleClickTime(); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool IsWindowEnabled(HandleRef hWnd); + + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + public static extern IntPtr GetCursor(); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern int ShowCursor(bool show); + + [DllImport(ExternDll.User32, EntryPoint = "GetMonitorInfo", CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool IntGetMonitorInfo(HandleRef hmonitor, [In, Out]NativeMethods.MONITORINFOEX info); + + [DllImport(ExternDll.User32, SetLastError = true, ExactSpelling = true)] + public static extern IntPtr MonitorFromWindow(HandleRef handle, int flags); + +#if BASE_NATIVEMETHODS + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + internal static extern int MapVirtualKey(int nVirtKey, int nMapType); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern IntPtr SetCapture(HandleRef hwnd); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern IntPtr SetCursor(HandleRef hcursor); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern IntPtr SetCursor(SafeHandle hcursor); + + [DllImport(ExternDll.User32, ExactSpelling=true, SetLastError=true)] + public static extern bool TrackMouseEvent(NativeMethods.TRACKMOUSEEVENT tme); + + [DllImport(ExternDll.User32, CharSet=System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] + public static extern NativeMethods.CursorHandle LoadCursor(HandleRef hInst, IntPtr iconId); + +#endif + +#if BASE_NATIVEMETHODS || CORE_NATIVEMETHODS || FRAMEWORK_NATIVEMETHODS + [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + public static extern int GetTickCount(); + +#endif + + [DllImport(ExternDll.User32, EntryPoint="ScreenToClient", SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern int IntScreenToClient(HandleRef hWnd, [In, Out] NativeMethods.POINT pt); + +#if BASE_NATIVEMETHODS + [DllImport(ExternDll.User32)] + public static extern int MessageBeep(int uType); +#endif + [DllImport(ExternDll.WtsApi32, SetLastError = true, EntryPoint = "WTSQuerySessionInformation", CharSet = CharSet.Auto)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool WTSQuerySessionInformation( + [In]IntPtr hServer, + [In] int SessionId, + [In]NativeMethods.WTS_INFO_CLASS WTSInfoClass, + [Out]out IntPtr ppBuffer, [Out]out int BytesReturned); + + [DllImport(ExternDll.WtsApi32, EntryPoint = "WTSFreeMemory", CharSet = CharSet.Auto)] + public static extern bool WTSFreeMemory([In]IntPtr pMemory); + } + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/SafeNativeMethodsOther.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/SafeNativeMethodsOther.cs new file mode 100644 index 00000000000..92e82ed2b6b --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/SafeNativeMethodsOther.cs @@ -0,0 +1,345 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +namespace MS.Win32 { + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.ComTypes; + using System; + using System.Security; + using System.Security.Permissions; + using System.Collections; + using System.IO; + using System.Text; + using System.ComponentModel; + using System.Diagnostics; + + + using IComDataObject = System.Runtime.InteropServices.ComTypes.IDataObject; + +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif DRT + using MS.Internal.Drt; +#else +#error Attempt to use FriendAccessAllowedAttribute from an unknown assembly. + using MS.Internal.YourAssemblyName; +#endif + + // + // Critical - This entire class is critical as it has SuppressUnmanagedCodeSecurity. + // TreatAsSafe - These Native methods have been reviewed as safe to call. + // + // The attributes are commented out here because this is a partial class and the attributes are already + // applied in SafeNativeMethodsCLR.cs + // + //[SecurityCritical, SecurityTreatAsSafe] + //[SuppressUnmanagedCodeSecurity] + [FriendAccessAllowed] + internal partial class SafeNativeMethods + { + ////////////////////////////// + // from Framework + + [Flags] + internal enum PlaySoundFlags + { + SND_SYNC = 0x00000000, /* play synchronously (default) */ + SND_ASYNC = 0x00000001, /* play asynchronously */ + SND_NODEFAULT = 0x00000002, /* silence (!default) if sound not found */ + SND_MEMORY = 0x00000004, /* pszSound points to a memory file */ + SND_LOOP = 0x00000008, /* loop the sound until next sndPlaySound */ + SND_NOSTOP = 0x00000010, /* don't stop any currently playing sound */ + SND_PURGE = 0x00000040, /* purge non-static events for task */ + SND_APPLICATION = 0x00000080, /* look for application specific association */ + SND_NOWAIT = 0x00002000, /* don't wait if the driver is busy */ + SND_ALIAS = 0x00010000, /* name is a registry alias */ + SND_FILENAME = 0x00020000, /* name is file name */ + SND_RESOURCE = 0x00040000, /* name is resource name or atom */ + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + internal static bool InSendMessage() + { + return SafeNativeMethodsPrivate.InSendMessage(); + } + + +#if never + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static int GetQueueStatus(uint flags) + { + return SafeNativeMethodsPrivate.GetQueueStatus(flags); + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + internal static int GetInputState() + { + return SafeNativeMethodsPrivate.GetInputState(); + } +#endif + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static bool IsUxThemeActive() { return SafeNativeMethodsPrivate.IsThemeActive() != 0; } + + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static bool SetCaretPos(int x, int y) + { + // To be consistent with our other PInvoke wrappers + // we should "throw" a Win32Exception on error here. + // But we don't want to introduce new "throws" w/o + // time to follow up on any new problems that causes. + + return SafeNativeMethodsPrivate.SetCaretPos(x,y); + } + + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static bool DestroyCaret() + { + // To be consistent with our other PInvoke wrappers + // we should "throw" a Win32Exception on error here. + // But we don't want to introduce new "throws" w/o + // time to follow up on any new problems that causes. + + return SafeNativeMethodsPrivate.DestroyCaret(); + } + + // NOTE: CLR has this in UnsafeNativeMethodsCLR.cs. Not sure why it is unsafe - need to follow up. + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static int GetCaretBlinkTime() + { + // To be consistent with our other PInvoke wrappers + // we should "throw" a Win32Exception on error here. + // But we don't want to introduce new "throws" w/o + // time to follow up on any new problems that causes. + + return SafeNativeMethodsPrivate.GetCaretBlinkTime(); + } + + // Constants for GetStringTypeEx. + public const uint CT_CTYPE1 = 1; + public const uint CT_CTYPE2 = 2; + public const uint CT_CTYPE3 = 4; + + public const UInt16 C1_SPACE = 0x0008; + public const UInt16 C1_PUNCT = 0x0010; + public const UInt16 C1_BLANK = 0x0040; + + public const UInt16 C3_NONSPACING = 0x0001; + public const UInt16 C3_DIACRITIC = 0x0002; + public const UInt16 C3_VOWELMARK = 0x0004; + public const UInt16 C3_KATAKANA = 0x0010; + public const UInt16 C3_HIRAGANA = 0x0020; + public const UInt16 C3_HALFWIDTH = 0x0040; + public const UInt16 C3_FULLWIDTH = 0x0080; + public const UInt16 C3_IDEOGRAPH = 0x0100; + public const UInt16 C3_KASHIDA = 0x0200; + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: This function is safe to call + /// + [SecurityCritical, SecurityTreatAsSafe] + public static bool GetStringTypeEx(uint locale, uint infoType, char[] sourceString, int count, + UInt16[] charTypes) + { + bool win32Return = SafeNativeMethodsPrivate.GetStringTypeEx(locale, infoType, sourceString, count, charTypes); + int win32Error = Marshal.GetLastWin32Error(); + + if (!win32Return) + { + throw new Win32Exception(win32Error); + } + + return win32Return; + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static int GetSysColor(int nIndex) + { + return SafeNativeMethodsPrivate.GetSysColor(nIndex); + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: Exposes no critical data and doesn't affect clipboard state + /// + [SecurityCritical, SecurityTreatAsSafe] + public static bool IsClipboardFormatAvailable(int format) + { + return SafeNativeMethodsPrivate.IsClipboardFormatAvailable(format); + } + +#if never + [DllImport(ExternDll.User32, EntryPoint = "DestroyIcon", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] + private static extern bool IntDestroyIcon(NativeMethods.IconHandle hIcon); + internal static void DestroyIcon(NativeMethods.IconHandle hIcon) + { + if (IntDestroyIcon(hIcon) == false) + { + throw new Win32Exception(); + } + } +#endif + ///////////////////////////// + // Used by BASE and FRAMEWORK + +#if FRAMEWORK_NATIVEMETHODS || BASE_NATIVEMETHODS + + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static bool IsDebuggerPresent() { return SafeNativeMethodsPrivate.IsDebuggerPresent(); } +#endif +#if BASE_NATIVEMETHODS + + ///////////////////// + // used by BASE + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static void QueryPerformanceCounter(out long lpPerformanceCount) + { + if (!SafeNativeMethodsPrivate.QueryPerformanceCounter(out lpPerformanceCount)) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + public static void QueryPerformanceFrequency(out long lpFrequency) + { + if (!SafeNativeMethodsPrivate.QueryPerformanceFrequency(out lpFrequency)) + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// TreatAsSafe: This function is safe to call + /// + [SecurityCritical,SecurityTreatAsSafe] + internal static int GetMessageTime() + { + return SafeNativeMethodsPrivate.GetMessageTime(); + } +#endif // BASE_NATIVEMETHODS + + + /// + /// This method accesses an UnsafeNativeMethod under an elevation. This is + /// still safe because it just returns the style or ex style which we consider safe. + /// + [SecurityCritical,SecurityTreatAsSafe] + internal static Int32 GetWindowStyle(HandleRef hWnd, bool exStyle) + { + int nIndex = exStyle ? NativeMethods.GWL_EXSTYLE : NativeMethods.GWL_STYLE; + return UnsafeNativeMethods.GetWindowLong(hWnd, nIndex); + } + [SuppressUnmanagedCodeSecurity] + private static partial class SafeNativeMethodsPrivate + { + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + internal static extern bool InSendMessage(); + +// [DllImport(ExternDll.User32, ExactSpelling = true)] +// public static extern int GetQueueStatus(uint flags); + +// [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] +// internal static extern int GetInputState(); + + [DllImport(ExternDll.Uxtheme, CharSet = CharSet.Unicode)] + public static extern int IsThemeActive(); + + [DllImport(ExternDll.User32, SetLastError=true, CharSet=CharSet.Auto)] + public static extern bool SetCaretPos(int x, int y); + + [DllImport(ExternDll.User32, SetLastError=true, CharSet=CharSet.Auto)] + public static extern bool DestroyCaret(); + + // NOTE: CLR has this in UnsafeNativeMethodsCLR.cs. Not sure why it is unsafe - need to follow up. + [DllImport(ExternDll.User32, SetLastError=true, CharSet=CharSet.Auto)] + public static extern int GetCaretBlinkTime(); + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern bool GetStringTypeEx(uint locale, uint infoType, char[] sourceString, int count, + [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] UInt16[] charTypes); + + [DllImport(ExternDll.User32, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern int GetSysColor(int nIndex); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern bool IsClipboardFormatAvailable(int format); + +#if FRAMEWORK_NATIVEMETHODS || BASE_NATIVEMETHODS + + [DllImport("kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto)] + internal static extern bool IsDebuggerPresent(); +#endif +#if BASE_NATIVEMETHODS + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool QueryPerformanceCounter(out long lpPerformanceCount); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool QueryPerformanceFrequency(out long lpFrequency); + + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + internal static extern int GetMessageTime(); +#endif + } + + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/SafeSystemMetrics.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/SafeSystemMetrics.cs new file mode 100644 index 00000000000..f170b2dba3c --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/SafeSystemMetrics.cs @@ -0,0 +1,159 @@ +//------------------------------------------------------------------------------ +// Microsoft Avalon +// Copyright (c) Microsoft Corporation, 2004 +// +// File: SafeSystemMetrics.cs +// This class is copied from the system metrics class in frameworks. The +// reason it exists is to consolidate all system metric calls through one layer +// so that maintenance from a security stand point gets easier. We will add +// mertrics on a need basis. The caching code is removed since the original calls +// that were moved here do not rely on caching. If there is a percieved perf. problem +// we can work on enabling this. +//------------------------------------------------------------------------------ +using System; +using System.Collections; +using System.Runtime.InteropServices; +using System.Windows.Media; +using Microsoft.Win32; +using System.Security; +using System.Security.Permissions; +using MS.Win32; +using MS.Internal; +using MS.Internal.Interop; + +using MS.Internal.PresentationCore; + +namespace MS.Win32 +{ + /// + /// Contains properties that are queries into the system's various settings. + /// + [FriendAccessAllowed] // Built into Core, also used by Framework. + internal sealed class SafeSystemMetrics + { + + private SafeSystemMetrics() + { + } + +#if !PRESENTATION_CORE + /// + /// Maps to SM_CXVIRTUALSCREEN + /// + /// + /// TreatAsSafe --There exists a demand + /// Security Critical -- Calling UnsafeNativeMethods + /// + internal static int VirtualScreenWidth + { + [SecurityCritical,SecurityTreatAsSafe] + get + { + SecurityHelper.DemandUnmanagedCode(); + + return UnsafeNativeMethods.GetSystemMetrics(SM.CXVIRTUALSCREEN); + } + } + + /// + /// Maps to SM_CYVIRTUALSCREEN + /// + /// + /// TreatAsSafe --There exists a demand + /// Security Critical -- Calling UnsafeNativeMethods + /// + internal static int VirtualScreenHeight + { + [SecurityCritical,SecurityTreatAsSafe] + get + { + SecurityHelper.DemandUnmanagedCode(); + return UnsafeNativeMethods.GetSystemMetrics(SM.CYVIRTUALSCREEN); + } + } +#endif //end !PRESENTATIONCORE + + /// + /// Maps to SM_CXDOUBLECLK + /// + /// + /// TreatAsSafe --This data is safe to expose + /// Security Critical -- Calling UnsafeNativeMethods + /// + internal static int DoubleClickDeltaX + { + [SecurityCritical, SecurityTreatAsSafe] + get + { + return UnsafeNativeMethods.GetSystemMetrics(SM.CXDOUBLECLK); + } + } + + /// + /// Maps to SM_CYDOUBLECLK + /// + /// + /// TreatAsSafe --This data is safe to expose + /// Security Critical -- Calling UnsafeNativeMethods + /// + internal static int DoubleClickDeltaY + { + [SecurityCritical, SecurityTreatAsSafe] + get + { + return UnsafeNativeMethods.GetSystemMetrics(SM.CYDOUBLECLK); + } + } + + + /// + /// Maps to SM_CXDRAG + /// + /// + /// TreatAsSafe --This data is safe to expose + /// Security Critical -- Calling UnsafeNativeMethods + /// + internal static int DragDeltaX + { + [SecurityCritical, SecurityTreatAsSafe] + get + { + return UnsafeNativeMethods.GetSystemMetrics(SM.CXDRAG); + } + } + + /// + /// Maps to SM_CYDRAG + /// + /// + /// TreatAsSafe --This data is safe to expose + /// Security Critical -- Calling UnsafeNativeMethods + /// + internal static int DragDeltaY + { + [SecurityCritical, SecurityTreatAsSafe] + get + { + return UnsafeNativeMethods.GetSystemMetrics(SM.CYDRAG); + } + } + + /// + /// Is an IMM enabled ? Maps to SM_IMMENABLED + /// + /// + ///Critical - calls a method that performs an elevation. + /// TreatAsSafe - data is considered safe to expose. + /// + internal static bool IsImmEnabled + { + [SecurityCritical, SecurityTreatAsSafe] + get + { + return (UnsafeNativeMethods.GetSystemMetrics(SM.IMMENABLED) != 0); + } + + } + + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCLR.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCLR.cs new file mode 100644 index 00000000000..c6c3f47b7cf --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCLR.cs @@ -0,0 +1,4236 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +namespace MS.Win32 +{ + using Accessibility; + using System.Runtime.InteropServices; + using System.Runtime.InteropServices.ComTypes; + using System.Runtime.ConstrainedExecution; + using System; + using System.Security.Permissions; + using System.Collections; + using System.IO; + using System.Text; + using System.Security; + using System.Diagnostics; + using System.ComponentModel; +#if !DRT && !UIAUTOMATIONTYPES + using MS.Internal.Interop; +#endif + + // DRTs cannot access MS.Internal +#if !DRT && !UIAUTOMATIONTYPES + using HR = MS.Internal.Interop.HRESULT; +#endif + + //The SecurityHelper class differs between assemblies and could not actually be + // shared, so it is duplicated across namespaces to prevent name collision. +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif UIAUTOMATIONTYPES + using MS.Internal.UIAutomationTypes; +#elif DRT + using MS.Internal.Drt; +#else +#error Attempt to use a class (duplicated across multiple namespaces) from an unknown assembly. +#endif + + using IComDataObject = System.Runtime.InteropServices.ComTypes.IDataObject; + + internal partial class UnsafeNativeMethods { + + private struct POINTSTRUCT { + public int x; + public int y; + + public POINTSTRUCT(int x, int y) { + this.x = x; + this.y = y; + } + } + + // For some reason "PtrToStructure" requires super high permission. + /// + /// Critical: The code below has a link demand for unmanaged code permission.This code can be used to + /// get to data that a pointer points to which can lead to easier data reading. + /// + [SecurityCritical] + public static object PtrToStructure(IntPtr lparam, Type cls) { + return Marshal.PtrToStructure(lparam, cls); + } + + // For some reason "StructureToPtr" requires super high permission. + /// + /// Critical: The code below has a link demand for unmanaged code permission.This code can be used to + /// write data to arbitrary memory. + /// + [SecurityCritical] + public static void StructureToPtr(object structure, IntPtr ptr, bool fDeleteOld) + { + Marshal.StructureToPtr(structure, ptr, fDeleteOld); + } + +#if BASE_NATIVEMETHODS + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Ole32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern int OleGetClipboard(ref IComDataObject data); + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern int OleSetClipboard(IComDataObject pDataObj); + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern int OleFlushClipboard(); +#endif + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Uxtheme, CharSet = CharSet.Auto, BestFitMapping = false)] + public static extern int GetCurrentThemeName(StringBuilder pszThemeFileName, int dwMaxNameChars, StringBuilder pszColorBuff, int dwMaxColorChars, StringBuilder pszSizeBuff, int cchMaxSizeChars); + + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.DwmAPI, BestFitMapping = false)] + public static extern int DwmIsCompositionEnabled(out Int32 enabled); + + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern IntPtr GetCurrentThread(); + +#if !DRT && !UIAUTOMATIONTYPES + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.User32, CharSet = System.Runtime.InteropServices.CharSet.Auto, BestFitMapping = false)] + public static extern WindowMessage RegisterWindowMessage(string msg); +#endif + + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.User32, EntryPoint = "SetWindowPos", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] + public static extern bool SetWindowPos(HandleRef hWnd, HandleRef hWndInsertAfter, int x, int y, int cx, int cy, int flags); + + /// + /// Critical: This code escalates to unmanaged code permission + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] + public static extern IntPtr GetWindow(HandleRef hWnd, int uCmd); + + public enum MonitorOpts : int + { + MONITOR_DEFAULTTONULL = 0x00000000, + MONITOR_DEFAULTTOPRIMARY = 0x00000001, + MONITOR_DEFAULTTONEAREST = 0x00000002, + } + + public enum MonitorDpiType + { + MDT_Effective_DPI = 0, + MDT_Angular_DPI = 1, + MDT_Raw_DPI = 2, + } + + public enum ProcessDpiAwareness + { + Process_DPI_Unaware = 0, + Process_System_DPI_Aware = 1, + Process_Per_Monitor_DPI_Aware = 2 + } + + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Shcore, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] + public static extern uint GetProcessDpiAwareness(HandleRef hProcess, out IntPtr awareness); + + /// + /// Critical: This code escalates to unmanaged code permission + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Shcore, CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)] + public static extern uint GetDpiForMonitor(HandleRef hMonitor, MonitorDpiType dpiType, out uint dpiX, out uint dpiY); + + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.User32, EntryPoint = "IsProcessDPIAware", CharSet = CharSet.Auto, SetLastError = true)] + internal static extern bool IsProcessDPIAware(); + + /// + /// Critical: This code escalates to unmanaged code permission + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Kernel32, CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr OpenProcess(int dwDesiredAccess, bool fInherit, int dwProcessId); + + /// + /// Critical: This code escalates to unmanaged code permission + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.User32, EntryPoint = "EnableNonClientDpiScaling", CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool EnableNonClientDpiScaling(HandleRef hWnd); + + /// + /// Critical: This code escalates to unmanaged code permission + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.User32, SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto, BestFitMapping = false)] + public static extern int GetClassName(HandleRef hwnd, StringBuilder lpClassName, int nMaxCount); + + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.User32, SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto, BestFitMapping = false)] + public static extern int MessageBox(HandleRef hWnd, string text, string caption, int type); + + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Uxtheme, CharSet = CharSet.Auto, BestFitMapping = false, EntryPoint = "SetWindowTheme")] + public static extern int CriticalSetWindowTheme(HandleRef hWnd, string subAppName, string subIdList); + + + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, EntryPoint = "CreateCompatibleBitmap", CharSet = CharSet.Auto)] + public static extern IntPtr CreateCompatibleBitmap(HandleRef hDC, int width, int height); + + /// + /// Critical - elevates via a SUC. Can be used to run arbitrary code. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, EntryPoint = "CreateCompatibleBitmap", CharSet = CharSet.Auto)] + public static extern IntPtr CriticalCreateCompatibleBitmap(HandleRef hDC, int width, int height); + + /// + /// Critical - elevates via a SUC. Can be used to run arbitrary code. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Gdi32, EntryPoint = "GetStockObject", SetLastError = true, CharSet = CharSet.Auto)] + public static extern IntPtr CriticalGetStockObject(int stockObject); + + /// + /// Critical - elevates via a SUC. Can be used to run arbitrary code. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint = "FillRect", SetLastError = true, CharSet = CharSet.Auto)] + public static extern int CriticalFillRect(IntPtr hdc, ref NativeMethods.RECT rcFill, IntPtr brush); + + /// + /// Critical: This code escalates to unmanaged code permission + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern int GetBitmapBits(HandleRef hbmp, int cbBuffer, byte[] lpvBits); + + /// + /// Critical: This code escalates to unmanaged code permission + /// + [SecurityCritical,SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool ShowWindow(HandleRef hWnd, int nCmdShow); + + /// + /// Critical: This code escalates to unmanaged code permission + /// + [SecurityCritical] + public static void DeleteObject(HandleRef hObject) + { + HandleCollector.Remove((IntPtr)hObject, NativeMethods.CommonHandles.GDI); + + if (!IntDeleteObject(hObject)) + { + throw new Win32Exception(); + } + } + + /// + /// Critical: This code escalates to unmanaged code permission via a call to IntDeleteObject + /// + [SecurityCritical] + public static bool DeleteObjectNoThrow(HandleRef hObject) + { + HandleCollector.Remove((IntPtr)hObject, NativeMethods.CommonHandles.GDI); + + bool result = IntDeleteObject(hObject); + int error = Marshal.GetLastWin32Error(); + + if(!result) + { + Debug.WriteLine("DeleteObject failed. Error = " + error); + } + + return result; + } + + + /// + /// Critical: This code escalates to unmanaged code permission + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling = true, EntryPoint="DeleteObject", CharSet=System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool IntDeleteObject(HandleRef hObject); + + + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern IntPtr SelectObject(HandleRef hdc, IntPtr obj); + + /// + /// Critical: This code escalates to unmanaged code permission + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern IntPtr SelectObject(HandleRef hdc, NativeMethods.BitmapHandle obj); + + /// + /// Critical: This code escalates to unmanaged code permission + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Gdi32, EntryPoint="SelectObject", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern IntPtr CriticalSelectObject(HandleRef hdc, IntPtr obj); + + [DllImport(ExternDll.User32, CharSet = System.Runtime.InteropServices.CharSet.Auto, BestFitMapping = false, SetLastError = true)] + public static extern int GetClipboardFormatName(int format, StringBuilder lpString, int cchMax); + + /// + /// This code elevates to unmanaged code permission + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto, BestFitMapping = false)] + public static extern int RegisterClipboardFormat(string format); + + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool BitBlt(HandleRef hDC, int x, int y, int nWidth, int nHeight, + HandleRef hSrcDC, int xSrc, int ySrc, int dwRop); + /// + /// This code elevates to unmanaged code permission + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint="PrintWindow", SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool CriticalPrintWindow(HandleRef hWnd, HandleRef hDC, int flags); + + /// + /// This code elevates to unmanaged code permission + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint="RedrawWindow", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool CriticalRedrawWindow(HandleRef hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, int flags); + + [DllImport(ExternDll.Shell32, CharSet=CharSet.Auto, BestFitMapping = false)] + public static extern int DragQueryFile(HandleRef hDrop, int iFile, StringBuilder lpszFile, int cch); + + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Shell32, CharSet=CharSet.Auto, BestFitMapping = false)] + public static extern IntPtr ShellExecute(HandleRef hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd); + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + internal class ShellExecuteInfo + { + public int cbSize; + public ShellExecuteFlags fMask; + public IntPtr hwnd; + public string lpVerb; + public string lpFile; + public string lpParameters; + public string lpDirectory; + public int nShow; + public IntPtr hInstApp; + public IntPtr lpIDList; + public string lpClass; + public IntPtr hkeyClass; + public int dwHotKey; + public IntPtr hIcon; + public IntPtr hProcess; + } + + [Flags] + internal enum ShellExecuteFlags + { + SEE_MASK_CLASSNAME = 0x00000001, + SEE_MASK_CLASSKEY = 0x00000003, + SEE_MASK_NOCLOSEPROCESS = 0x00000040, + SEE_MASK_FLAG_DDEWAIT = 0x00000100, + SEE_MASK_DOENVSUBST = 0x00000200, + SEE_MASK_FLAG_NO_UI = 0x00000400, + SEE_MASK_UNICODE = 0x00004000, + SEE_MASK_NO_CONSOLE = 0x00008000, + SEE_MASK_ASYNCOK = 0x00100000, + SEE_MASK_HMONITOR = 0x00200000, + SEE_MASK_NOZONECHECKS = 0x00800000, + SEE_MASK_NOQUERYCLASSSTORE = 0x01000000, + SEE_MASK_WAITFORINPUTIDLE = 0x02000000 + }; + + /// + /// Critical - elevates via SUC. Starts a new process. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Shell32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern bool ShellExecuteEx([In, Out] ShellExecuteInfo lpExecInfo); + + public const int MB_PRECOMPOSED = 0x00000001; + public const int MB_COMPOSITE = 0x00000002; + public const int MB_USEGLYPHCHARS = 0x00000004; + public const int MB_ERR_INVALID_CHARS = 0x00000008; + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Kernel32, ExactSpelling=true, CharSet=CharSet.Unicode, SetLastError=true)] + public static extern int MultiByteToWideChar(int CodePage, int dwFlags, byte[] lpMultiByteStr, int cchMultiByte, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpWideCharStr, int cchWideChar); + /// + /// Critical - elevates (via SuppressUnmanagedCodeSecurity). + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Kernel32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] + public static extern int WideCharToMultiByte(int codePage, int flags, [MarshalAs(UnmanagedType.LPWStr)]string wideStr, int chars, [In,Out]byte[] pOutBytes, int bufferBytes, IntPtr defaultChar, IntPtr pDefaultUsed); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, ExactSpelling=true, EntryPoint="RtlMoveMemory", CharSet=CharSet.Unicode)] + public static extern void CopyMemoryW(IntPtr pdst, string psrc, int cb); + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, ExactSpelling = true, EntryPoint = "RtlMoveMemory", CharSet = CharSet.Unicode)] + public static extern void CopyMemoryW(IntPtr pdst, char[] psrc, int cb); + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, ExactSpelling=true, EntryPoint="RtlMoveMemory")] + public static extern void CopyMemory(IntPtr pdst, byte[] psrc, int cb); + +#if BASE_NATIVEMETHODS + /// + /// Critical as this code performs an elevation due to an unmanaged code call. Also this + /// information can be used to exploit the system. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint="GetKeyboardState", CharSet=CharSet.Auto, SetLastError=true)] + private static extern int IntGetKeyboardState(byte [] keystate); + [SecurityCritical] + public static void GetKeyboardState(byte [] keystate) + { + if(IntGetKeyboardState(keystate) == 0) + { + throw new Win32Exception(); + } + } +#endif + +#if DRT_NATIVEMETHODS + [DllImport(ExternDll.User32, ExactSpelling=true, EntryPoint="keybd_event", CharSet=CharSet.Auto)] + public static extern void Keybd_event(byte vk, byte scan, int flags, IntPtr extrainfo); +#endif + +#if !DRT && !UIAUTOMATIONTYPES + /// + /// Critical: This code elevates to unmanaged code permission + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, EntryPoint = "GetModuleFileName", CharSet=CharSet.Unicode, SetLastError = true)] + private static extern int IntGetModuleFileName(HandleRef hModule, StringBuilder buffer, int length); + + /// + /// Critical: This code elevates to unmanaged code permission by calling into IntGetModuleFileName + /// + [SecurityCritical] + internal static string GetModuleFileName(HandleRef hModule) + { + // .Net is currently far behind Windows with regard to supporting paths longer than MAX_PATH. + // At one point it was tested trying to load UNC paths longer than MAX_PATH and mscorlib threw + // FileIOExceptions before WPF was even on the stack. + // All the same, we still want to have this grow-and-retry logic because the CLR can be hosted + // in a native application. Callers bothering to use this rather than Assembly based reflection + // are likely doing so because of (at least the potential for) the returned name referring to a + // native module. + StringBuilder buffer = new StringBuilder(Win32Constant.MAX_PATH); + while (true) + { + int size = IntGetModuleFileName(hModule, buffer, buffer.Capacity); + if (size == 0) + { + throw new Win32Exception(); + } + + // GetModuleFileName returns nSize when it's truncated but does NOT set the last error. + // MSDN documentation says this has changed in Windows 2000+. + if (size == buffer.Capacity) + { + // Enlarge the buffer and try again. + buffer.EnsureCapacity(buffer.Capacity * 2); + continue; + } + + return buffer.ToString(); + } + } +#endif + + +#if BASE_NATIVEMETHODS + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern bool TranslateMessage([In, Out] ref System.Windows.Interop.MSG msg); + + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] + public static extern IntPtr DispatchMessage([In] ref System.Windows.Interop.MSG msg); +#endif + +#if BASE_NATIVEMETHODS + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, CharSet=CharSet.Auto, EntryPoint="PostThreadMessage", SetLastError=true)] + private static extern int IntPostThreadMessage(int id, int msg, IntPtr wparam, IntPtr lparam); + [SecurityCritical] + public static void PostThreadMessage(int id, int msg, IntPtr wparam, IntPtr lparam) + { + if(IntPostThreadMessage(id, msg, wparam, lparam) == 0) + { + throw new Win32Exception(); + } + } +#endif + + /// + /// Critical - This code elevates to unmanaged code. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport("oleacc.dll")] + internal static extern int ObjectFromLresult(IntPtr lResult, ref Guid iid, IntPtr wParam, [In, Out] ref IAccessible ppvObject); + + /// + /// Critical - This code elevates to unmanaged code. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport("user32.dll")] + internal static extern bool IsWinEventHookInstalled(int winevent); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Ole32, EntryPoint="OleInitialize")] + private static extern int IntOleInitialize(IntPtr val); + + [SecurityCritical] + public static int OleInitialize() + { + return IntOleInitialize(IntPtr.Zero); + } + + /// + /// Critical: SUC. Inherently unsafe. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Ole32)] + public static extern int CoRegisterPSClsid(ref Guid riid, ref Guid rclsid); + + + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public extern static bool EnumThreadWindows(int dwThreadId, NativeMethods.EnumThreadWindowsCallback lpfn, HandleRef lParam); + + /// + /// Critical: This code calls into unmanaged code which elevates + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=CharSet.Auto, SetLastError=true)] + public static extern int OleUninitialize(); + + [DllImport(ExternDll.Kernel32, EntryPoint="CloseHandle", CharSet=CharSet.Auto, SetLastError=true)] + private static extern bool IntCloseHandle(HandleRef handle); + + /// + /// Critical: Closes a passed in handle, LinkDemand on Marshal.GetLastWin32Error + /// + [SecurityCritical] + public static bool CloseHandleNoThrow(HandleRef handle) + { + HandleCollector.Remove((IntPtr)handle, NativeMethods.CommonHandles.Kernel); + + bool result = IntCloseHandle(handle); + int error = Marshal.GetLastWin32Error(); + + if(!result) + { + Debug.WriteLine("CloseHandle failed. Error = " + error); + } + + return result; + + } + + /// + /// Critical as this code performs an UnmanagedCodeSecurity elevation. + /// + [SecurityCritical] + [DllImport(ExternDll.Ole32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern int CreateStreamOnHGlobal(IntPtr hGlobal, bool fDeleteOnRelease, ref System.Runtime.InteropServices.ComTypes.IStream istream); + +#if BASE_NATIVEMETHODS + [DllImport(ExternDll.Gdi32, SetLastError=true, EntryPoint="CreateCompatibleDC", CharSet=CharSet.Auto)] + private static extern IntPtr IntCreateCompatibleDC(HandleRef hDC); + + + /// + /// Critical - elevates via a SUC. Can be used to run arbitrary code. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Gdi32, SetLastError=true, EntryPoint="CreateCompatibleDC", CharSet=CharSet.Auto)] + public static extern IntPtr CriticalCreateCompatibleDC(HandleRef hDC); + + /// + /// Critical: LinkDemand on Win32Exception constructor + /// TreatAsSafe: Throwing an exception isn't unsafe + /// Note: If SupressUnmanagedCodeSecurity attribute is ever added to IntCreateCompatibleDC, we need to be Critical + /// + [SecurityCritical, SecurityTreatAsSafe] + public static IntPtr CreateCompatibleDC(HandleRef hDC) + { + IntPtr h = IntCreateCompatibleDC(hDC); + if(h == IntPtr.Zero) + { + throw new Win32Exception(); + } + + return HandleCollector.Add(h, NativeMethods.CommonHandles.HDC); + } +#endif + + [DllImport(ExternDll.Kernel32, EntryPoint="UnmapViewOfFile", CharSet=CharSet.Auto, SetLastError=true)] + private static extern bool IntUnmapViewOfFile(HandleRef pvBaseAddress); + /* + /// + /// Critical: LinkDemand on Win32Exception constructor + /// TreatAsSafe: Throwing an exception isn't unsafe + /// Note: If SupressUnmanagedCodeSecurity attribute is ever added to IntUnmapViewOfFile, we need to be Critical + /// + [SecurityCritical, SecurityTreatAsSafe] + public static void UnmapViewOfFile(HandleRef pvBaseAddress) + { + HandleCollector.Remove((IntPtr)pvBaseAddress, NativeMethods.CommonHandles.Kernel); + if(IntUnmapViewOfFile(pvBaseAddress) == 0) + { + throw new Win32Exception(); + } + } + */ + /// + /// Critical: Unmaps a file handle, LinkDemand on Marshal.GetLastWin32Error + /// + [SecurityCritical] + public static bool UnmapViewOfFileNoThrow(HandleRef pvBaseAddress) + { + HandleCollector.Remove((IntPtr)pvBaseAddress, NativeMethods.CommonHandles.Kernel); + + bool result = IntUnmapViewOfFile(pvBaseAddress); + int error = Marshal.GetLastWin32Error(); + + if(!result) + { + Debug.WriteLine("UnmapViewOfFile failed. Error = " + error); + } + + return result; + } + + + /// + /// Critical: This code calls into unmanaged code which elevates + /// + [SecurityCritical] + public static bool EnableWindow(HandleRef hWnd, bool enable) + { + bool result = NativeMethodsSetLastError.EnableWindow(hWnd, enable); + if(!result) + { + int win32Err = Marshal.GetLastWin32Error(); + if(win32Err != 0) + { + throw new Win32Exception(win32Err); + } + } + + return result; + } + + /// + /// Critical: This code calls into unmanaged code which elevates + /// + [SecurityCritical] + public static bool EnableWindowNoThrow(HandleRef hWnd, bool enable) + { + // This method is not throwing because the caller don't want to fail after calling this. + // If the window was not previously disabled, the return value is zero, else it is non-zero. + return NativeMethodsSetLastError.EnableWindow(hWnd, enable); + } + + // GetObject stuff + [DllImport(ExternDll.Gdi32, SetLastError=true, CharSet=CharSet.Auto)] + public static extern int GetObject(HandleRef hObject, int nSize, [In, Out] NativeMethods.BITMAP bm); + + /// + /// Critical: This code returns the window which has focus and elevates to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern IntPtr GetFocus(); + + /// + /// Critical - this code elevates via SUC. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint = "GetCursorPos", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + private static extern bool IntGetCursorPos([In, Out] NativeMethods.POINT pt); + + /// + /// Critical - calls a critical function. + /// + [SecurityCritical] + internal static bool GetCursorPos([In, Out] NativeMethods.POINT pt) + { + bool returnValue = IntGetCursorPos(pt); + if (returnValue == false) + { + throw new Win32Exception(); + } + return returnValue; + } + + /// + /// Critical - this code elevates via SUC. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint = "GetCursorPos", ExactSpelling = true, CharSet = CharSet.Auto)] + private static extern bool IntTryGetCursorPos([In, Out] NativeMethods.POINT pt); + + /// + /// Critical - calls a critical function. + /// + [SecurityCritical] + internal static bool TryGetCursorPos([In, Out] NativeMethods.POINT pt) + { + bool returnValue = IntTryGetCursorPos(pt); + + // Sometimes Win32 will fail this call, such as if you are + // not running in the interactive desktop. For example, + // a secure screen saver may be running. + if (returnValue == false) + { + System.Diagnostics.Debug.WriteLine("GetCursorPos failed!"); + + pt.x = 0; + pt.y = 0; + } + return returnValue; + } + +#if BASE_NATIVEMETHODS || CORE_NATIVEMETHODS || FRAMEWORK_NATIVEMETHODS + /// + /// Critical:Unmanaged code that gets the state of the keyboard keys + /// This can be exploited to get keyboard state. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + public static extern int GetWindowThreadProcessId(HandleRef hWnd, out int lpdwProcessId); + + /// + /// Critical:Unmanaged code that gets the state of the keyboard keys + /// This can be exploited to get keyboard state. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern short GetKeyState(int keyCode); + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Ole32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto, PreserveSig = false)] + public static extern void DoDragDrop(IComDataObject dataObject, UnsafeNativeMethods.IOleDropSource dropSource, int allowedEffects, int[] finalEffect); + + /// + /// Critical - this code elevates via SUC. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=CharSet.Auto)] + internal static extern void ReleaseStgMedium(ref STGMEDIUM medium); + + /// + /// Critical - this code elevates via SUC. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool InvalidateRect(HandleRef hWnd, IntPtr rect, bool erase); + + +#endif + + + /// + /// SecurityCritical due to a call to SetLastError and calls GetWindowText + /// + [SecurityCritical] + internal static int GetWindowText(HandleRef hWnd, [Out] StringBuilder lpString, int nMaxCount) + { + int returnValue = NativeMethodsSetLastError.GetWindowText(hWnd, lpString, nMaxCount); + if (returnValue == 0) + { + int win32Err = Marshal.GetLastWin32Error(); + if (win32Err != 0) + { + throw new Win32Exception(win32Err); + } + } + return returnValue; + } + + /// + /// SecurityCritical due to a call to SetLastError + /// + [SecurityCritical] + internal static int GetWindowTextLength(HandleRef hWnd) + { + int returnValue = NativeMethodsSetLastError.GetWindowTextLength(hWnd); + if (returnValue == 0) + { + int win32Err = Marshal.GetLastWin32Error(); + if (win32Err != 0) + { + throw new Win32Exception(win32Err); + } + } + return returnValue; + } + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr GlobalAlloc(int uFlags, IntPtr dwBytes); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr GlobalReAlloc(HandleRef handle, IntPtr bytes, int flags); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr GlobalLock(HandleRef handle); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool GlobalUnlock(HandleRef handle); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr GlobalFree(HandleRef handle); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr GlobalSize(HandleRef handle); + +#if BASE_NATIVEMETHODS || CORE_NATIVEMETHODS || FRAMEWORK_NATIVEMETHODS + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet=CharSet.Auto)] + public static extern bool ImmSetConversionStatus(HandleRef hIMC, int conversion, int sentence); + + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet=CharSet.Auto)] + public static extern bool ImmGetConversionStatus(HandleRef hIMC, ref int conversion, ref int sentence); + + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern IntPtr ImmGetContext(HandleRef hWnd); + + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern bool ImmReleaseContext(HandleRef hWnd, HandleRef hIMC); + + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet=CharSet.Auto)] + public static extern IntPtr ImmAssociateContext(HandleRef hWnd, HandleRef hIMC); + + + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern bool ImmSetOpenStatus(HandleRef hIMC, bool open); + + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern bool ImmGetOpenStatus(HandleRef hIMC); + + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern bool ImmNotifyIME(HandleRef hIMC, int dwAction, int dwIndex, int dwValue); + + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet=CharSet.Auto)] + public static extern int ImmGetProperty(HandleRef hkl, int flags); + + // ImmGetCompositionString for result and composition strings + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern int ImmGetCompositionString(HandleRef hIMC, int dwIndex, char[] lpBuf, int dwBufLen); + + // ImmGetCompositionString for display attributes + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern int ImmGetCompositionString(HandleRef hIMC, int dwIndex, byte[] lpBuf, int dwBufLen); + + // ImmGetCompositionString for clause information + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern int ImmGetCompositionString(HandleRef hIMC, int dwIndex, int[] lpBuf, int dwBufLen); + + // ImmGetCompositionString for query information + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern int ImmGetCompositionString(HandleRef hIMC, int dwIndex, IntPtr lpBuf, int dwBufLen); + + //[DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + //public static extern int ImmSetCompositionFont(HandleRef hIMC, [In, Out] ref NativeMethods.LOGFONT lf); + + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern int ImmConfigureIME(HandleRef hkl, HandleRef hwnd, int dwData, IntPtr pvoid); + + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern int ImmConfigureIME(HandleRef hkl, HandleRef hwnd, int dwData, [In] ref NativeMethods.REGISTERWORD registerWord); + + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern int ImmSetCompositionWindow(HandleRef hIMC, [In, Out] ref NativeMethods.COMPOSITIONFORM compform); + + /// + /// Critical:This code causes an elevation of privilige to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern int ImmSetCandidateWindow(HandleRef hIMC, [In, Out] ref NativeMethods.CANDIDATEFORM candform); + + [DllImport(ExternDll.Imm32, CharSet = CharSet.Auto)] + public static extern IntPtr ImmGetDefaultIMEWnd(HandleRef hwnd); +#endif + + /// + /// Critical - calls SetFocusWrapper (the real PInvoke method) + /// + [SecurityCritical] + internal static IntPtr SetFocus(HandleRef hWnd) + { + IntPtr result = IntPtr.Zero; + + if(!TrySetFocus(hWnd, ref result)) + { + throw new Win32Exception(); + } + + return result; + } + + /// + /// Critical - calls SetFocusWrapper (the real PInvoke method) + /// + [SecurityCritical] + internal static bool TrySetFocus(HandleRef hWnd) + { + IntPtr result = IntPtr.Zero; + return TrySetFocus(hWnd, ref result); + } + + /// + /// Critical - calls SetFocusWrapper (the real PInvoke method) + /// + [SecurityCritical] + internal static bool TrySetFocus(HandleRef hWnd, ref IntPtr result) + { + result = NativeMethodsSetLastError.SetFocus(hWnd); + int errorCode = Marshal.GetLastWin32Error(); + + if (result == IntPtr.Zero && errorCode != 0) + { + return false; + } + + return true; + } + + /// + /// Critical - This code returns a critical resource and calls critical code. + /// + [SecurityCritical] + internal static IntPtr GetParent(HandleRef hWnd) + { + IntPtr retVal = NativeMethodsSetLastError.GetParent(hWnd); + int errorCode = Marshal.GetLastWin32Error(); + + if (retVal == IntPtr.Zero && errorCode != 0) + { + throw new Win32Exception(errorCode); + } + + return retVal; + } + + /// + /// Critical - This code returns a critical resource and causes unmanaged code elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern IntPtr GetAncestor(HandleRef hWnd, int flags); + + /// + /// Critical - This code causes unmanaged code elevation. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.User32, SetLastError = true, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern bool IsChild(HandleRef hWndParent, HandleRef hwnd); + + + //***************** + // + // if you're thinking of enabling either of the functions below. + // you should first take a look at SafeSecurityHelper.TransformGlobalRectToLocal & TransformLocalRectToScreen + // they likely do what you typically use the function for - and it's safe to use. + // if you use the function below - you will get exceptions in partial trust. + // anyquestions - email avsee. + // + //****************** + + + /// + /// Critical as this code performs an elevation. + /// + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + [ SecurityCritical, SuppressUnmanagedCodeSecurity] + public static extern IntPtr SetParent(HandleRef hWnd, HandleRef hWndParent); + + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, EntryPoint = "GetModuleHandle", CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true, SetLastError = true)] + private static extern IntPtr IntGetModuleHandle(string modName); + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + internal static IntPtr GetModuleHandle(string modName) + { + IntPtr retVal = IntGetModuleHandle(modName); + + if (retVal == IntPtr.Zero) + { + throw new Win32Exception(); + } + + return retVal; + } + + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] + public static extern IntPtr CallWindowProc(IntPtr wndProc, IntPtr hWnd, int msg, + IntPtr wParam, IntPtr lParam); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, CharSet = CharSet.Unicode, EntryPoint = "DefWindowProcW")] + public static extern IntPtr DefWindowProc(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, SetLastError=true, EntryPoint="GetProcAddress", CharSet=CharSet.Ansi, BestFitMapping=false)] + public static extern IntPtr IntGetProcAddress(HandleRef hModule, string lpProcName); + + /// + /// Critical - calls IntGetProcAddress (the real PInvoke method) + /// + [SecurityCritical] + public static IntPtr GetProcAddress(HandleRef hModule, string lpProcName) + { + IntPtr result = IntGetProcAddress(hModule, lpProcName); + if(result == IntPtr.Zero) + { + throw new Win32Exception(); + } + + return result; + } + + // GetProcAddress Note : The lpProcName parameter can identify the DLL function by specifying an ordinal value associated + // with the function in the EXPORTS statement. GetProcAddress verifies that the specified ordinal is in + // the range 1 through the highest ordinal value exported in the .def file. The function then uses the + // ordinal as an index to read the function's address from a function table. If the .def file does not number + // the functions consecutively from 1 to N (where N is the number of exported functions), an error can + // occur where GetProcAddress returns an invalid, non-NULL address, even though there is no function with the specified ordinal. + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, EntryPoint="GetProcAddress", CharSet=CharSet.Ansi, BestFitMapping=false)] + public static extern IntPtr GetProcAddressNoThrow(HandleRef hModule, string lpProcName); + + /// + /// Critical: as suppressing UnmanagedCodeSecurity + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, CharSet = CharSet.Unicode)] + public static extern IntPtr LoadLibrary(string lpFileName); + + [Flags] + internal enum LoadLibraryFlags : uint + { + None = 0x00000000, + /// + /// If this value is used, and the executable module is a DLL, the system does + /// not call DllMain for process and thread initialization and termination. + /// Also, the system does not load additional executable modules that are + /// referenced by the specified module. + /// + /// + /// Do not use this value; it is provided only for backward compatibility. + /// If you are planning to access only data or resources in the DLL, use + /// or + /// or + /// or both. Otherwise, load the library as a DLL or executable module + /// using the function. + /// + DONT_RESOLVE_DLL_REFERENCES = 0x00000001, + /// + /// If this value is used, the system does not check AppLocker rules or apply + /// Software Restriction Policies for the DLL. This action applies only to the + /// DLL being loaded and not to its dependencies. This value is recommended + /// for use in setup programs that must run extracted DLLs during installation. + /// + /// + /// Windows Server 2008 R2 and Windows 7: + /// On systems with KB2532445 installed, the + /// caller must be running as "LocalSystem" or "TrustedInstaller"; otherwise the + /// system ignores this flag. For more information, see "You can circumvent AppLocker + /// rules by using an Office macro on a computer that is running Windows 7 or + /// Windows Server 2008 R2" in the Help and Support Knowledge Base + /// at + /// + /// Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: + /// AppLocker was introduced in Windows 7 and Windows Server 2008 R2. + /// + LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010, + /// + /// If this value is used, the system maps the file into the calling process's + /// virtual address space as if it were a data file. Nothing is done to execute + /// or prepare to execute the mapped file. Therefore, you cannot call functions + /// like GetModuleFileName, GetModuleHandle or GetProcAddress with this DLL. + /// Using this value causes writes to read-only memory to raise an access violation. + /// Use this flag when you want to load a DLL only to extract messages or resources + /// from it.This value can be used with . + /// + LOAD_LIBRARY_AS_DATAFILE = 0x00000002, + /// + /// Similar to LOAD_LIBRARY_AS_DATAFILE, except that the DLL file is opened with + /// exclusive write access for the calling process. Other processes cannot open + /// the DLL file for write access while it is in use. However, the DLL can + /// still be opened by other processes. This value can be used with + /// . + /// + /// + /// Windows Server 2003 and Windows XP: This value is not supported until + /// Windows Vista. + /// + LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040, + /// + /// If this value is used, the system maps the file into the process's virtual + /// address space as an image file. However, the loader does not load the static + /// imports or perform the other usual initialization steps. Use this flag when + /// you want to load a DLL only to extract messages or resources from it. Unless + /// the application depends on the file having the in-memory layout of an image, + /// this value should be used with either or + /// . + /// + /// + /// Windows Server 2003 and Windows XP: This value is not supported until Windows Vista. + /// + LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020, + /// + /// If this value is used, the application's installation directory is searched for the + /// DLL and its dependencies. Directories in the standard search path are not searched. + /// This value cannot be combined with . + /// + /// + /// Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008: + /// This value requires KB2533623 to be installed. + /// Windows Server 2003 and Windows XP: + /// This value is not supported. + /// + LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200, + /// + /// This value is a combination of , + /// , and . + /// Directories in the standard search path are not searched. This value cannot be combined with + /// . This value represents the recommended maximum number + /// of directories an application should include in its DLL search path. + /// + /// + /// Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008: + /// This value requires KB2533623 to be installed. + /// + /// Windows Server 2003 and Windows XP: + /// This value is not supported. + /// + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000, + /// + /// If this value is used, the directory that contains the DLL is temporarily added to + /// the beginning of the list of directories that are searched for the DLL's dependencies. + /// Directories in the standard search path are not searched. + /// + /// The lpFileName parameter must specify a fully qualified path. This value cannot be + /// combined with . + /// + /// For example, if Lib2.dll is a dependency of C:\Dir1\Lib1.dll, loading Lib1.dll with + /// this value causes the system to search for Lib2.dll only in C:\Dir1. To search for + /// Lib2.dll in C:\Dir1 and all of the directories in the DLL search path, combine this + /// value with . + /// + /// + /// Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008: + /// This value requires KB2533623 to be installed. + /// + /// Windows Server 2003 and Windows XP: + /// This value is not supported. + /// + LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100, + /// + /// If this value is used, %windows%\system32 is searched for the DLL and its dependencies. + /// Directories in the standard search path are not searched. This value cannot be + /// combined with + /// + /// + /// Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008: + /// This value requires KB2533623 to be installed. + /// Windows Server 2003 and Windows XP: + /// This value is not supported. + /// + LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800, + /// + /// If this value is used, directories added using the AddDllDirectory or the SetDllDirectory + /// function are searched for the DLL and its dependencies. If more than one directory has been added, + /// the order in which the directories are searched is unspecified. Directories in the + /// standard search path are not searched. This value cannot be combined with + /// + /// + /// + /// Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008: + /// This value requires KB2533623 to be installed. + /// Windows Server 2003 and Windows XP: + /// This value is not supported. + /// + LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400, + /// + /// If this value is used and lpFileName specifies an absolute path, the system uses the alternate + /// file search strategy discussed in the Remarks section to find associated executable modules that + /// the specified module causes to be loaded. If this value is used and lpFileName specifies a + /// relative path, the behavior is undefined. If this value is not used, or if lpFileName does not specify a path, + /// the system uses the standard search strategy discussed in the Remarks section to find associated + /// executable modules that the specified module causes to be loaded.This value cannot be combined with + /// any LOAD_LIBRARY_SEARCH flag. + /// + LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008 + } + + /// + /// Do not use this - instead use + /// + [SuppressUnmanagedCodeSecurity] + [SecurityCritical] + [Obsolete("Use LoadLibraryHelper.SafeLoadLibraryEx instead")] + [DllImport(ExternDll.Kernel32, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern IntPtr LoadLibraryEx([In][MarshalAs(UnmanagedType.LPTStr)]string lpFileName, IntPtr hFile, [In] LoadLibraryFlags dwFlags); + + [Flags] + internal enum GetModuleHandleFlags : uint + { + None = 0x00000000, + /// + /// The lpModuleName parameter in is an address + /// in the module. + /// + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 0x00000004, + /// + /// The module stays loaded until the process is terminated, no matter how many times + /// FreeLibrary is called. + /// This option cannot be used with . + /// + GET_MODULE_HANDLE_EX_FLAG_PIN = 0x00000001, + /// + /// The reference count for the module is not incremented. This option is equivalent to the + /// behavior of GetModuleHandle. Do not pass the retrieved module handle to the FreeLibrary + /// function; doing so can cause the DLL to be unmapped prematurely. + /// This option cannot be used with . + /// + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 0x00000002 + } + + [SuppressUnmanagedCodeSecurity] + [SecurityCritical] + [DllImport(ExternDll.Kernel32, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool GetModuleHandleEx( + [In] GetModuleHandleFlags dwFlags, + [In][Optional][MarshalAs(UnmanagedType.LPTStr)] string lpModuleName, + [Out] out IntPtr hModule); + + [SuppressUnmanagedCodeSecurity] + [SecurityCritical] + [DllImport(ExternDll.Kernel32, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool FreeLibrary([In] IntPtr hModule); + +#if !DRT && !UIAUTOMATIONTYPES + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32)] + public static extern int GetSystemMetrics(SM nIndex); +#endif + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true, CharSet=CharSet.Auto, BestFitMapping = false)] + public static extern bool SystemParametersInfo(int nAction, int nParam, ref NativeMethods.RECT rc, int nUpdate); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)] + public static extern bool SystemParametersInfo(int nAction, int nParam, ref int value, int ignore); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)] + public static extern bool SystemParametersInfo(int nAction, int nParam, ref bool value, int ignore); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)] + public static extern bool SystemParametersInfo(int nAction, int nParam, ref NativeMethods.HIGHCONTRAST_I rc, int nUpdate); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)] + public static extern bool SystemParametersInfo(int nAction, int nParam, [In, Out] NativeMethods.NONCLIENTMETRICS metrics, int nUpdate); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, CharSet = CharSet.Auto, ExactSpelling = true)] + public static extern bool GetSystemPowerStatus(ref NativeMethods.SYSTEM_POWER_STATUS systemPowerStatus); + + /// + /// Critical - performs an elevation via SUC. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint="ClientToScreen", SetLastError=true, ExactSpelling=true, CharSet=CharSet.Auto)] + private static extern int IntClientToScreen(HandleRef hWnd, [In, Out] NativeMethods.POINT pt); + + /// + /// Critical calls critical code - IntClientToScreen + /// + [SecurityCritical] + public static void ClientToScreen(HandleRef hWnd, [In, Out] NativeMethods.POINT pt) + { + if(IntClientToScreen(hWnd, pt) == 0) + { + throw new Win32Exception(); + } + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern IntPtr GetDesktopWindow(); + + /// + /// Critical:Elevates to Unmanaged code permission and can be used to + /// change the foreground window. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern IntPtr GetForegroundWindow(); + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern int RegisterDragDrop(HandleRef hwnd, UnsafeNativeMethods.IOleDropTarget target); + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern int RevokeDragDrop(HandleRef hwnd); + +#if !DRT && !UIAUTOMATIONTYPES + /// + /// Critical:Elevates to Unmanaged code permission and can be used to + /// get information of messages in queues. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] + public static extern bool PeekMessage([In, Out] ref System.Windows.Interop.MSG msg, HandleRef hwnd, WindowMessage msgMin, WindowMessage msgMax, int remove); + +#if BASE_NATIVEMETHODS + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, BestFitMapping = false, CharSet=CharSet.Auto)] + public static extern bool SetProp(HandleRef hWnd, string propName, HandleRef data); + +#endif + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint = "PostMessage", CharSet = CharSet.Auto, SetLastError = true)] + private static extern bool IntPostMessage(HandleRef hwnd, WindowMessage msg, IntPtr wparam, IntPtr lparam); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + internal static void PostMessage(HandleRef hwnd, WindowMessage msg, IntPtr wparam, IntPtr lparam) + { + if (!IntPostMessage(hwnd, msg, wparam, lparam)) + { + throw new Win32Exception(); + } + } + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint = "PostMessage", CharSet = CharSet.Auto)] + internal static extern bool TryPostMessage(HandleRef hwnd, WindowMessage msg, IntPtr wparam, IntPtr lparam); +#endif +#if BASE_NATIVEMETHODS || CORE_NATIVEMETHODS + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern void NotifyWinEvent(int winEvent, HandleRef hwnd, int objType, int objID); +#endif + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling = true, EntryPoint = "BeginPaint", CharSet = CharSet.Auto)] + private static extern IntPtr IntBeginPaint(HandleRef hWnd, [In, Out] ref NativeMethods.PAINTSTRUCT lpPaint); + + /// + /// Critical as this code performs an elevation. via the call to IntBeginPaint + /// + [SecurityCritical] + public static IntPtr BeginPaint(HandleRef hWnd, [In, Out, MarshalAs(UnmanagedType.LPStruct)] ref NativeMethods.PAINTSTRUCT lpPaint) { + return HandleCollector.Add(IntBeginPaint(hWnd, ref lpPaint), NativeMethods.CommonHandles.HDC); + } + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling = true, EntryPoint = "EndPaint", CharSet = CharSet.Auto)] + private static extern bool IntEndPaint(HandleRef hWnd, ref NativeMethods.PAINTSTRUCT lpPaint); + /// + /// Critical as this code performs an elevation via the call to IntEndPaint. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + public static bool EndPaint(HandleRef hWnd, [In, MarshalAs(UnmanagedType.LPStruct)] ref NativeMethods.PAINTSTRUCT lpPaint) { + HandleCollector.Remove(lpPaint.hdc, NativeMethods.CommonHandles.HDC); + return IntEndPaint(hWnd, ref lpPaint); + } + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true, ExactSpelling = true, EntryPoint = "GetDC", CharSet = CharSet.Auto)] + private static extern IntPtr IntGetDC(HandleRef hWnd); + /// + /// Critical as this code performs an elevation. The call to handle collector is + /// by itself not dangerous because handle collector simply + /// stores a count of the number of instances of a given + /// handle and not the handle itself. + /// + [SecurityCritical] + public static IntPtr GetDC(HandleRef hWnd) + { + IntPtr hDc = IntGetDC(hWnd); + if(hDc == IntPtr.Zero) + { + throw new Win32Exception(); + } + + return HandleCollector.Add(hDc, NativeMethods.CommonHandles.HDC); + } + + /// + /// Critical as this code performs an elevation.The call to handle collector + /// is by itself not dangerous because handle collector simply + /// stores a count of the number of instances of a given handle and not the handle itself. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling = true, EntryPoint = "ReleaseDC", CharSet = CharSet.Auto)] + private static extern int IntReleaseDC(HandleRef hWnd, HandleRef hDC); + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + public static int ReleaseDC(HandleRef hWnd, HandleRef hDC) { + HandleCollector.Remove((IntPtr)hDC, NativeMethods.CommonHandles.HDC); + return IntReleaseDC(hWnd, hDC); + } + + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern int GetDeviceCaps(HandleRef hDC, int nIndex); + + /// + /// Critical as this code performs an elevation to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern IntPtr GetActiveWindow(); + + /// + /// Critical as this code performs an elevation to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern bool SetForegroundWindow(HandleRef hWnd); + + // Begin API Additions to support common dialog controls + /// + /// Critical as this code performs an elevation to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Comdlg32, SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + internal static extern int CommDlgExtendedError(); + + /// + /// Critical as this code performs an elevation to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Comdlg32, SetLastError = true, CharSet = CharSet.Unicode)] + internal static extern bool GetOpenFileName([In, Out] NativeMethods.OPENFILENAME_I ofn); + + /// + /// Critical as this code performs an elevation to unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Comdlg32, SetLastError = true, CharSet = CharSet.Unicode)] + internal static extern bool GetSaveFileName([In, Out] NativeMethods.OPENFILENAME_I ofn); + // End Common Dialog API Additions + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [return:MarshalAs(UnmanagedType.Bool)] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto, SetLastError=true)] + public static extern bool SetLayeredWindowAttributes(HandleRef hwnd, int crKey, byte bAlpha, int dwFlags); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.Bool)] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, NativeMethods.POINT pptDst, NativeMethods.POINT pSizeDst, IntPtr hdcSrc, NativeMethods.POINT pptSrc, int crKey, ref NativeMethods.BLENDFUNCTION pBlend, int dwFlags); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true)] + public static extern IntPtr SetActiveWindow(HandleRef hWnd); + + //TODO: Refactor shared native methods so that parser dependency + // is in separate file. PS # 30845. +#if PBTCOMPILER + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern IntPtr SetCursor(HandleRef hcursor); +#endif + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + + [DllImport(ExternDll.User32, ExactSpelling=true, EntryPoint="DestroyCursor", CharSet=CharSet.Auto)] + private static extern bool IntDestroyCursor(IntPtr hCurs); + + /// + /// Critical calls IntDestroyCursor + /// + [SecurityCritical] + public static bool DestroyCursor(IntPtr hCurs) { + return IntDestroyCursor(hCurs); + } + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint="DestroyIcon", CharSet=System.Runtime.InteropServices.CharSet.Auto, SetLastError=true)] + private static extern bool IntDestroyIcon(IntPtr hIcon); + + /// + /// Critical: calls a critical method (IntDestroyIcon) + /// + [SecurityCritical] + public static bool DestroyIcon(IntPtr hIcon) + { + bool result = IntDestroyIcon(hIcon); + int error = Marshal.GetLastWin32Error(); + + if(!result) + { + // To be consistent with out other PInvoke wrappers + // we should "throw" here. But we don't want to + // introduce new "throws" w/o time to follow up on any + // new problems that causes. + Debug.WriteLine("DestroyIcon failed. Error = " + error); + //throw new Win32Exception(); + } + + return result; + } + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Gdi32, EntryPoint="DeleteObject", CharSet=System.Runtime.InteropServices.CharSet.Auto, SetLastError=true)] + private static extern bool IntDeleteObject(IntPtr hObject); + + /// + /// Critical: calls a critical method (IntDeleteObject) + /// + [SecurityCritical] + public static bool DeleteObject(IntPtr hObject) + { + bool result = IntDeleteObject(hObject); + int error = Marshal.GetLastWin32Error(); + + if(!result) + { + // To be consistent with out other PInvoke wrappers + // we should "throw" here. But we don't want to + // introduce new "throws" w/o time to follow up on any + // new problems that causes. + Debug.WriteLine("DeleteObject failed. Error = " + error); + //throw new Win32Exception(); + } + + return result; + } + +#if BASE_NATIVEMETHODS || CORE_NATIVEMETHODS || FRAMEWORK_NATIVEMETHODS + /// + /// Critical as suppressing UnmanagedCodeSecurity + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = "CreateDIBSection")] + private static extern NativeMethods.BitmapHandle PrivateCreateDIBSection(HandleRef hdc, ref NativeMethods.BITMAPINFO bitmapInfo, int iUsage, ref IntPtr ppvBits, SafeFileMappingHandle hSection, int dwOffset); + /// + /// Critical - The method invokes PrivateCreateDIBSection. + /// + [SecurityCritical] + internal static NativeMethods.BitmapHandle CreateDIBSection(HandleRef hdc, ref NativeMethods.BITMAPINFO bitmapInfo, int iUsage, ref IntPtr ppvBits, SafeFileMappingHandle hSection, int dwOffset) + { + if (hSection == null) + { + // PInvoke marshalling does not handle null SafeHandle, we must pass an IntPtr.Zero backed SafeHandle + hSection = new SafeFileMappingHandle(IntPtr.Zero); + } + + NativeMethods.BitmapHandle hBitmap = PrivateCreateDIBSection(hdc, ref bitmapInfo, iUsage, ref ppvBits, hSection, dwOffset); + int error = Marshal.GetLastWin32Error(); + + if ( hBitmap.IsInvalid ) + { + Debug.WriteLine("CreateDIBSection failed. Error = " + error); + } + + return hBitmap; + } +#endif + + /// + /// Critical as suppressing UnmanagedCodeSecurity + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = "CreateBitmap")] + private static extern NativeMethods.BitmapHandle PrivateCreateBitmap(int width, int height, int planes, int bitsPerPixel, byte[] lpvBits); + /// + /// Critical - The method invokes PrivateCreateBitmap. + /// + [SecurityCritical] + internal static NativeMethods.BitmapHandle CreateBitmap(int width, int height, int planes, int bitsPerPixel, byte[] lpvBits) + { + NativeMethods.BitmapHandle hBitmap = PrivateCreateBitmap(width, height, planes, bitsPerPixel, lpvBits); + int error = Marshal.GetLastWin32Error(); + + if ( hBitmap.IsInvalid ) + { + Debug.WriteLine("CreateBitmap failed. Error = " + error); + } + + return hBitmap; + } + + /// + /// Critical as suppressing UnmanagedCodeSecurity + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = "DestroyIcon")] + private static extern bool PrivateDestroyIcon(HandleRef handle); + /// + /// Critical - The method invokes PrivateDestroyIcon. + /// + [SecurityCritical] + internal static bool DestroyIcon(HandleRef handle) + { + HandleCollector.Remove((IntPtr)handle, NativeMethods.CommonHandles.Icon); + + bool result = PrivateDestroyIcon(handle); + int error = Marshal.GetLastWin32Error(); + + if ( !result ) + { + Debug.WriteLine("DestroyIcon failed. Error = " + error); + } + + return result; + } + + /// + /// Critical as suppressing UnmanagedCodeSecurity + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = "CreateIconIndirect")] + private static extern NativeMethods.IconHandle PrivateCreateIconIndirect([In, MarshalAs(UnmanagedType.LPStruct)]NativeMethods.ICONINFO iconInfo); + /// + /// Critical - The method invokes PrivateCreateIconIndirect. + /// + [SecurityCritical] + internal static NativeMethods.IconHandle CreateIconIndirect([In, MarshalAs(UnmanagedType.LPStruct)]NativeMethods.ICONINFO iconInfo) + { + NativeMethods.IconHandle hIcon = PrivateCreateIconIndirect(iconInfo); + int error = Marshal.GetLastWin32Error(); + + if ( hIcon.IsInvalid ) + { + Debug.WriteLine("CreateIconIndirect failed. Error = " + error); + } + + return hIcon; + } + + /// + /// Critical: This code elevates to unmanaged code + /// + [SecurityCritical,SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] + public static extern bool IsWindow(HandleRef hWnd); + +#if BASE_NATIVEMETHODS + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="DeleteDC", CharSet=CharSet.Auto)] + private static extern bool IntDeleteDC(HandleRef hDC); + /// + /// Critical: LinkDemand on Win32Exception constructor + /// TreatAsSafe: Throwing an exception isn't unsafe + /// Note: If SupressUnmanagedCodeSecurity attribute is ever added to IntDeleteDC, we need to be Critical + /// + [SecurityCritical, SecurityTreatAsSafe] + public static void DeleteDC(HandleRef hDC) + { + HandleCollector.Remove((IntPtr)hDC, NativeMethods.CommonHandles.HDC); + if(!IntDeleteDC(hDC)) + { + throw new Win32Exception(); + } + } + + + /// + /// Critical: This code elevates to unmanaged code + /// + [SecurityCritical,SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Gdi32, SetLastError=true, ExactSpelling=true, EntryPoint="DeleteDC", CharSet=CharSet.Auto)] + private static extern bool IntCriticalDeleteDC(HandleRef hDC); + + /// + /// Critical: This code elevates to unmanaged code + /// + [SecurityCritical] + public static void CriticalDeleteDC(HandleRef hDC) + { + HandleCollector.Remove((IntPtr)hDC, NativeMethods.CommonHandles.HDC); + if(!IntCriticalDeleteDC(hDC)) + { + throw new Win32Exception(); + } + } +#endif + + +#if BASE_NATIVEMETHODS + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError=true, EntryPoint="GetMessageW", ExactSpelling=true, CharSet=CharSet.Unicode)] + private static extern int IntGetMessageW([In, Out] ref System.Windows.Interop.MSG msg, HandleRef hWnd, int uMsgFilterMin, int uMsgFilterMax); + /// + /// Critical - calls IntGetMessageW (the real PInvoke method) + /// + [SecurityCritical] + public static bool GetMessageW([In, Out] ref System.Windows.Interop.MSG msg, HandleRef hWnd, int uMsgFilterMin, int uMsgFilterMax) + { + bool boolResult = false; + + int result = IntGetMessageW(ref msg, hWnd, uMsgFilterMin, uMsgFilterMax); + if(result == -1) + { + throw new Win32Exception(); + } + else if(result == 0) + { + boolResult = false; + } + else + { + boolResult = true; + } + + return boolResult; + } + +#endif + +#if BASE_NATIVEMETHODS + + /// + /// Critical: This code elevates via a SUC to call into unmanaged Code and can get the HWND of windows at any arbitrary point on the screen + /// + [SecurityCritical,SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint="WindowFromPoint", ExactSpelling=true, CharSet=CharSet.Auto)] + private static extern IntPtr IntWindowFromPoint(POINTSTRUCT pt); + + /// + /// Critical: This calls WindowFromPoint(POINTSTRUCT) which is marked SecurityCritical + /// + [SecurityCritical] + public static IntPtr WindowFromPoint(int x, int y) { + POINTSTRUCT ps = new POINTSTRUCT(x, y); + return IntWindowFromPoint(ps); + } +#endif + + /// + /// Critical: This code elevates to call into unmanaged Code + /// + [SecurityCritical,SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint="CreateWindowEx", CharSet=CharSet.Auto, BestFitMapping = false, SetLastError=true)] + public static extern IntPtr IntCreateWindowEx(int dwExStyle, string lpszClassName, + string lpszWindowName, int style, int x, int y, int width, int height, + HandleRef hWndParent, HandleRef hMenu, HandleRef hInst, [MarshalAs(UnmanagedType.AsAny)] object pvParam); + + /// + /// Critical: This code elevates to call into unmanaged Code by calling IntCreateWindowEx + /// + [SecurityCritical] + public static IntPtr CreateWindowEx(int dwExStyle, string lpszClassName, + string lpszWindowName, int style, int x, int y, int width, int height, + HandleRef hWndParent, HandleRef hMenu, HandleRef hInst, [MarshalAs(UnmanagedType.AsAny)]object pvParam) { + IntPtr retVal = IntCreateWindowEx(dwExStyle, lpszClassName, + lpszWindowName, style, x, y, width, height, hWndParent, hMenu, + hInst, pvParam); + if(retVal == IntPtr.Zero) + { + throw new Win32Exception(); + } + return retVal; + } + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true, EntryPoint="DestroyWindow", CharSet=CharSet.Auto)] + public static extern bool IntDestroyWindow(HandleRef hWnd); + + /// + /// Critical - calls Security Critical method + /// + [SecurityCritical] + public static void DestroyWindow(HandleRef hWnd) + { + if(!IntDestroyWindow(hWnd)) + { + throw new Win32Exception(); + } + } + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.User32)] + internal static extern IntPtr SetWinEventHook(int eventMin, int eventMax, IntPtr hmodWinEventProc, NativeMethods.WinEventProcDef WinEventReentrancyFilter, uint idProcess, uint idThread, int dwFlags); + + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.User32)] + internal static extern bool UnhookWinEvent(IntPtr winEventHook); + + /// + /// Critical - Delegate invoked by elevated (via a SUC) pinvoke. + /// + [SecurityCritical] + public delegate bool EnumChildrenCallback(IntPtr hwnd, IntPtr lParam); + + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + public static void EnumChildWindows(HandleRef hwndParent, EnumChildrenCallback lpEnumFunc, HandleRef lParam) + { + // http://msdn.microsoft.com/en-us/library/ms633494(VS.85).aspx + // Return value is not used + IntEnumChildWindows(hwndParent, lpEnumFunc, lParam); + } + + /// + /// Critical - elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.User32, EntryPoint = "EnumChildWindows", ExactSpelling = true)] + private static extern bool IntEnumChildWindows(HandleRef hwndParent, EnumChildrenCallback lpEnumFunc, HandleRef lParam); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true, CharSet = CharSet.Auto)] + public static extern int GetWindowRgn(HandleRef hWnd, HandleRef hRgn); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true, CharSet = CharSet.Auto)] + public static extern bool PtInRegion(HandleRef hRgn, int X, int Y); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)] + public static extern IntPtr CreateRectRgn(int x1, int y1, int x2, int y2); + + // for GetUserNameEx + public enum EXTENDED_NAME_FORMAT { + NameUnknown = 0, + NameFullyQualifiedDN = 1, + NameSamCompatible = 2, + NameDisplay = 3, + NameUniqueId = 6, + NameCanonical = 7, + NameUserPrincipal = 8, + NameCanonicalEx = 9, + NameServicePrincipal = 10 + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("00000122-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleDropTarget { + + [PreserveSig] + int OleDragEnter( + [In, MarshalAs(UnmanagedType.Interface)] + object pDataObj, + [In, MarshalAs(UnmanagedType.U4)] + int grfKeyState, + [In, MarshalAs(UnmanagedType.U8)] + long pt, + [In, Out] + ref int pdwEffect); + + [PreserveSig] + int OleDragOver( + [In, MarshalAs(UnmanagedType.U4)] + int grfKeyState, + [In, MarshalAs(UnmanagedType.U8)] + long pt, + [In, Out] + ref int pdwEffect); + + [PreserveSig] + int OleDragLeave(); + + [PreserveSig] + int OleDrop( + [In, MarshalAs(UnmanagedType.Interface)] + object pDataObj, + [In, MarshalAs(UnmanagedType.U4)] + int grfKeyState, + [In, MarshalAs(UnmanagedType.U8)] + long pt, + [In, Out] + ref int pdwEffect); + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("00000121-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleDropSource { + + [PreserveSig] + int OleQueryContinueDrag( + int fEscapePressed, + [In, MarshalAs(UnmanagedType.U4)] + int grfKeyState); + + [PreserveSig] + int OleGiveFeedback( + [In, MarshalAs(UnmanagedType.U4)] + int dwEffect); + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ + ComImport(), + Guid("B196B289-BAB4-101A-B69C-00AA00341D07"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown) + ] + public interface IOleControlSite { + + [PreserveSig] + int OnControlInfoChanged(); + + [PreserveSig] + int LockInPlaceActive(int fLock); + + [PreserveSig] + int GetExtendedControl( + [Out, MarshalAs(UnmanagedType.IDispatch)] + out object ppDisp); + + [PreserveSig] + int TransformCoords( + [In, Out] + NativeMethods.POINT pPtlHimetric, + [In, Out] + NativeMethods.POINTF pPtfContainer, + [In, MarshalAs(UnmanagedType.U4)] + int dwFlags); + + [PreserveSig] + int TranslateAccelerator( + [In] + ref System.Windows.Interop.MSG pMsg, + [In, MarshalAs(UnmanagedType.U4)] + int grfModifiers); + + [PreserveSig] + int OnFocus(int fGotFocus); + + [PreserveSig] + int ShowPropertyFrame(); + + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("00000118-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleClientSite { + + [PreserveSig] + int SaveObject(); + + [PreserveSig] + int GetMoniker( + [In, MarshalAs(UnmanagedType.U4)] + int dwAssign, + [In, MarshalAs(UnmanagedType.U4)] + int dwWhichMoniker, + [Out, MarshalAs(UnmanagedType.Interface)] + out object moniker); + + [PreserveSig] + int GetContainer(out IOleContainer container); + + [PreserveSig] + int ShowObject(); + + [PreserveSig] + int OnShowWindow(int fShow); + + [PreserveSig] + int RequestNewObjectLayout(); + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("00000119-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleInPlaceSite { + + IntPtr GetWindow(); + + [PreserveSig] + int ContextSensitiveHelp(int fEnterMode); + + [PreserveSig] + int CanInPlaceActivate(); + + [PreserveSig] + int OnInPlaceActivate(); + + [PreserveSig] + int OnUIActivate(); + + [PreserveSig] + int GetWindowContext( + [Out, MarshalAs(UnmanagedType.Interface)] + out UnsafeNativeMethods.IOleInPlaceFrame ppFrame, + [Out, MarshalAs(UnmanagedType.Interface)] + out UnsafeNativeMethods.IOleInPlaceUIWindow ppDoc, + [Out] + NativeMethods.COMRECT lprcPosRect, + [Out] + NativeMethods.COMRECT lprcClipRect, + [In, Out] + NativeMethods.OLEINPLACEFRAMEINFO lpFrameInfo); + + [PreserveSig] + int Scroll( + NativeMethods.SIZE scrollExtant); + + [PreserveSig] + int OnUIDeactivate( + int fUndoable); + + [PreserveSig] + int OnInPlaceDeactivate(); + + [PreserveSig] + int DiscardUndoState(); + + [PreserveSig] + int DeactivateAndUndo(); + + [PreserveSig] + int OnPosRectChange( + [In] + NativeMethods.COMRECT lprcPosRect); + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("9BFBBC02-EFF1-101A-84ED-00AA00341D07"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPropertyNotifySink { + void OnChanged(int dispID); + + [PreserveSig] + int OnRequestEdit(int dispID); + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("00000100-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IEnumUnknown { + + [PreserveSig] + int Next( + [In, MarshalAs(UnmanagedType.U4)] + int celt, + [Out] + IntPtr rgelt, + IntPtr pceltFetched); + + [PreserveSig] + int Skip( + [In, MarshalAs(UnmanagedType.U4)] + int celt); + + void Reset(); + + void Clone( + [Out] + out IEnumUnknown ppenum); + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("0000011B-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleContainer { + + [PreserveSig] + int ParseDisplayName( + [In, MarshalAs(UnmanagedType.Interface)] + object pbc, + [In, MarshalAs(UnmanagedType.BStr)] + string pszDisplayName, + [Out, MarshalAs(UnmanagedType.LPArray)] + int[] pchEaten, + [Out, MarshalAs(UnmanagedType.LPArray)] + object[] ppmkOut); + + [PreserveSig] + int EnumObjects( + [In, MarshalAs(UnmanagedType.U4)] + int grfFlags, + [Out] + out IEnumUnknown ppenum); + + [PreserveSig] + int LockContainer( + bool fLock); + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("00000116-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleInPlaceFrame { + + IntPtr GetWindow(); + + [PreserveSig] + int ContextSensitiveHelp(int fEnterMode); + + [PreserveSig] + int GetBorder( + [Out] + NativeMethods.COMRECT lprectBorder); + + [PreserveSig] + int RequestBorderSpace( + [In] + NativeMethods.COMRECT pborderwidths); + + [PreserveSig] + int SetBorderSpace( + [In] + NativeMethods.COMRECT pborderwidths); + + [PreserveSig] + int SetActiveObject( + [In, MarshalAs(UnmanagedType.Interface)] + UnsafeNativeMethods.IOleInPlaceActiveObject pActiveObject, + [In, MarshalAs(UnmanagedType.LPWStr)] + string pszObjName); + + [PreserveSig] + int InsertMenus( + [In] + IntPtr hmenuShared, + [In, Out] + NativeMethods.tagOleMenuGroupWidths lpMenuWidths); + + [PreserveSig] + int SetMenu( + [In] + IntPtr hmenuShared, + [In] + IntPtr holemenu, + [In] + IntPtr hwndActiveObject); + + [PreserveSig] + int RemoveMenus( + [In] + IntPtr hmenuShared); + + [PreserveSig] + int SetStatusText( + [In, MarshalAs(UnmanagedType.LPWStr)] + string pszStatusText); + + [PreserveSig] + int EnableModeless( + bool fEnable); + + [PreserveSig] + int TranslateAccelerator( + [In] + ref System.Windows.Interop.MSG lpmsg, + [In, MarshalAs(UnmanagedType.U2)] + short wID); + } + + //IMPORTANT: Do not try to optimize perf here by changing the enum size to byte + //instead of int since this is used in COM Interop for browser hosting scenarios + // Enum for OLECMDIDs used by IOleCommandTarget in browser hosted scenarios + // Imported from the published header - docobj.h, If you need to support more + // than these OLECMDS, add it from that header file + public enum OLECMDID { + OLECMDID_SAVE = 3, + OLECMDID_SAVEAS = 4, + OLECMDID_PRINT = 6, + OLECMDID_PRINTPREVIEW = 7, + OLECMDID_PAGESETUP = 8, + OLECMDID_PROPERTIES = 10, + OLECMDID_CUT = 11, + OLECMDID_COPY = 12, + OLECMDID_PASTE = 13, + OLECMDID_SELECTALL = 17, + OLECMDID_REFRESH = 22, + OLECMDID_STOP = 23, + } + + public enum OLECMDEXECOPT { + OLECMDEXECOPT_DODEFAULT = 0, + OLECMDEXECOPT_PROMPTUSER = 1, + OLECMDEXECOPT_DONTPROMPTUSER = 2, + OLECMDEXECOPT_SHOWHELP = 3 + } + + // OLECMDID Flags used by IOleCommandTarget to specify status of commands in browser hosted scenarios + // Imported from the published header - docobj.h + public enum OLECMDF { + /// + /// The command is supported by this object + /// + OLECMDF_SUPPORTED = 0x1, + /// + /// The command is available and enabled + /// + OLECMDF_ENABLED = 0x2, + /// + /// The command is an on-off toggle and is currently on + /// + OLECMDF_LATCHED = 0x4, + /// + /// Reserved for future use + /// + OLECMDF_NINCHED = 0x8, + /// + /// Command is invisible + /// + OLECMDF_INVISIBLE = 0x10, + /// + /// Command should not be displayed in the context menu + /// + OLECMDF_DEFHIDEONCTXTMENU = 0x20 + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("00000115-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleInPlaceUIWindow { + IntPtr GetWindow(); + + [PreserveSig] + int ContextSensitiveHelp( + int fEnterMode); + + [PreserveSig] + int GetBorder( + [Out] + NativeMethods.RECT lprectBorder); + + [PreserveSig] + int RequestBorderSpace( + [In] + NativeMethods.RECT pborderwidths); + + [PreserveSig] + int SetBorderSpace( + [In] + NativeMethods.RECT pborderwidths); + + void SetActiveObject( + [In, MarshalAs(UnmanagedType.Interface)] + UnsafeNativeMethods.IOleInPlaceActiveObject pActiveObject, + [In, MarshalAs(UnmanagedType.LPWStr)] + string pszObjName); + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), + Guid("00000117-0000-0000-C000-000000000046"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleInPlaceActiveObject { + /// + /// Critical: SUC. Exposes a native window handle. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [PreserveSig] + int GetWindow(out IntPtr hwnd); + + void ContextSensitiveHelp( + int fEnterMode); + + /// + /// Critical: This code escalates to unmanaged code permission + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [PreserveSig] + int TranslateAccelerator( + [In] + ref System.Windows.Interop.MSG lpmsg); + + void OnFrameWindowActivate( + int fActivate); + + void OnDocWindowActivate( + int fActivate); + + void ResizeBorder( + [In] + NativeMethods.RECT prcBorder, + [In] + UnsafeNativeMethods.IOleInPlaceUIWindow pUIWindow, + bool fFrameWindow); + + void EnableModeless( + int fEnable); + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("00000114-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleWindow { + + [PreserveSig] + int GetWindow( [Out]out IntPtr hwnd ); + + + void ContextSensitiveHelp( + + int fEnterMode); + } + + /// + /// Critical - elevates via a SUC. + /// + [ SecurityCritical( SecurityCriticalScope.Everything ) , SuppressUnmanagedCodeSecurity ] + [ComImport(), + Guid("00000113-0000-0000-C000-000000000046"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleInPlaceObject { + + [PreserveSig] + int GetWindow( [Out]out IntPtr hwnd ); + + + void ContextSensitiveHelp( + + int fEnterMode); + + + void InPlaceDeactivate(); + + + [PreserveSig] + int UIDeactivate(); + + + void SetObjectRects( + [In] + NativeMethods.COMRECT lprcPosRect, + [In] + NativeMethods.COMRECT lprcClipRect); + + void ReactivateAndUndo(); + + + } + + /// + /// Critical - elevates via a SUC. + /// + [SecurityCritical( SecurityCriticalScope.Everything ) , SuppressUnmanagedCodeSecurity ] + [ComImport(), + Guid("00000112-0000-0000-C000-000000000046"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleObject { + + [PreserveSig] + int SetClientSite( + [In, MarshalAs(UnmanagedType.Interface)] + UnsafeNativeMethods.IOleClientSite pClientSite); + + + UnsafeNativeMethods.IOleClientSite GetClientSite(); + + [PreserveSig] + int SetHostNames( + [In, MarshalAs(UnmanagedType.LPWStr)] + string szContainerApp, + [In, MarshalAs(UnmanagedType.LPWStr)] + string szContainerObj); + + [PreserveSig] + int Close( + + int dwSaveOption); + + [PreserveSig] + int SetMoniker( + [In, MarshalAs(UnmanagedType.U4)] + int dwWhichMoniker, + [In, MarshalAs(UnmanagedType.Interface)] + object pmk); + + [PreserveSig] + int GetMoniker( + [In, MarshalAs(UnmanagedType.U4)] + int dwAssign, + [In, MarshalAs(UnmanagedType.U4)] + int dwWhichMoniker, + [Out, MarshalAs(UnmanagedType.Interface)] + out object moniker); + + [PreserveSig] + int InitFromData( + [In, MarshalAs(UnmanagedType.Interface)] + IComDataObject pDataObject, + + int fCreation, + [In, MarshalAs(UnmanagedType.U4)] + int dwReserved); + + [PreserveSig] + int GetClipboardData( + [In, MarshalAs(UnmanagedType.U4)] + int dwReserved, + out IComDataObject data); + + [PreserveSig] + int DoVerb( + + int iVerb, + [In] + IntPtr lpmsg, + [In, MarshalAs(UnmanagedType.Interface)] + UnsafeNativeMethods.IOleClientSite pActiveSite, + + int lindex, + + IntPtr hwndParent, + [In] + NativeMethods.COMRECT lprcPosRect); + + [PreserveSig] + int EnumVerbs(out UnsafeNativeMethods.IEnumOLEVERB e); + + [PreserveSig] + int OleUpdate(); + + [PreserveSig] + int IsUpToDate(); + + [PreserveSig] + int GetUserClassID( + [In, Out] + ref Guid pClsid); + + [PreserveSig] + int GetUserType( + [In, MarshalAs(UnmanagedType.U4)] + int dwFormOfType, + [Out, MarshalAs(UnmanagedType.LPWStr)] + out string userType); + + [PreserveSig] + int SetExtent( + [In, MarshalAs(UnmanagedType.U4)] + int dwDrawAspect, + [In] + NativeMethods.SIZE pSizel); + + [PreserveSig] + int GetExtent( + [In, MarshalAs(UnmanagedType.U4)] + int dwDrawAspect, + [Out] + NativeMethods.SIZE pSizel); + + [PreserveSig] + int Advise( + IAdviseSink pAdvSink, + out int cookie); + + [PreserveSig] + int Unadvise( + [In, MarshalAs(UnmanagedType.U4)] + int dwConnection); + + [PreserveSig] + int EnumAdvise(out IEnumSTATDATA e); + + [PreserveSig] + int GetMiscStatus( + [In, MarshalAs(UnmanagedType.U4)] + int dwAspect, + out int misc); + + [PreserveSig] + int SetColorScheme( + [In] + NativeMethods.tagLOGPALETTE pLogpal); + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("1C2056CC-5EF4-101B-8BC8-00AA003E3B29"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleInPlaceObjectWindowless { + + [PreserveSig] + int SetClientSite( + [In, MarshalAs(UnmanagedType.Interface)] + UnsafeNativeMethods.IOleClientSite pClientSite); + + [PreserveSig] + int GetClientSite(out UnsafeNativeMethods.IOleClientSite site); + + [PreserveSig] + int SetHostNames( + [In, MarshalAs(UnmanagedType.LPWStr)] + string szContainerApp, + [In, MarshalAs(UnmanagedType.LPWStr)] + string szContainerObj); + + [PreserveSig] + int Close( + + int dwSaveOption); + + [PreserveSig] + int SetMoniker( + [In, MarshalAs(UnmanagedType.U4)] + int dwWhichMoniker, + [In, MarshalAs(UnmanagedType.Interface)] + object pmk); + + [PreserveSig] + int GetMoniker( + [In, MarshalAs(UnmanagedType.U4)] + int dwAssign, + [In, MarshalAs(UnmanagedType.U4)] + int dwWhichMoniker, + [Out, MarshalAs(UnmanagedType.Interface)] + out object moniker); + + [PreserveSig] + int InitFromData( + [In, MarshalAs(UnmanagedType.Interface)] + IComDataObject pDataObject, + + int fCreation, + [In, MarshalAs(UnmanagedType.U4)] + int dwReserved); + + [PreserveSig] + int GetClipboardData( + [In, MarshalAs(UnmanagedType.U4)] + int dwReserved, + out IComDataObject data); + + [PreserveSig] + int DoVerb( + + int iVerb, + [In] + IntPtr lpmsg, + [In, MarshalAs(UnmanagedType.Interface)] + UnsafeNativeMethods.IOleClientSite pActiveSite, + + int lindex, + + IntPtr hwndParent, + [In] + NativeMethods.RECT lprcPosRect); + + [PreserveSig] + int EnumVerbs(out UnsafeNativeMethods.IEnumOLEVERB e); + + [PreserveSig] + int OleUpdate(); + + [PreserveSig] + int IsUpToDate(); + + [PreserveSig] + int GetUserClassID( + [In, Out] + ref Guid pClsid); + + [PreserveSig] + int GetUserType( + [In, MarshalAs(UnmanagedType.U4)] + int dwFormOfType, + [Out, MarshalAs(UnmanagedType.LPWStr)] + out string userType); + + [PreserveSig] + int SetExtent( + [In, MarshalAs(UnmanagedType.U4)] + int dwDrawAspect, + [In] + NativeMethods.SIZE pSizel); + + [PreserveSig] + int GetExtent( + [In, MarshalAs(UnmanagedType.U4)] + int dwDrawAspect, + [Out] + NativeMethods.SIZE pSizel); + + [PreserveSig] + int Advise( + [In, MarshalAs(UnmanagedType.Interface)] + IAdviseSink pAdvSink, + out int cookie); + + [PreserveSig] + int Unadvise( + [In, MarshalAs(UnmanagedType.U4)] + int dwConnection); + + [PreserveSig] + int EnumAdvise(out IEnumSTATDATA e); + + [PreserveSig] + int GetMiscStatus( + [In, MarshalAs(UnmanagedType.U4)] + int dwAspect, + out int misc); + + [PreserveSig] + int SetColorScheme( + [In] + NativeMethods.tagLOGPALETTE pLogpal); + + [PreserveSig] + int OnWindowMessage( + [In, MarshalAs(UnmanagedType.U4)] int msg, + [In, MarshalAs(UnmanagedType.U4)] int wParam, + [In, MarshalAs(UnmanagedType.U4)] int lParam, + [Out, MarshalAs(UnmanagedType.U4)] int plResult); + + [PreserveSig] + int GetDropTarget( + [Out, MarshalAs(UnmanagedType.Interface)] object ppDropTarget); + + }; + + /// + /// Critical - elevates via a SUC. + /// + [SecurityCritical( SecurityCriticalScope.Everything ) , SuppressUnmanagedCodeSecurity ] + [ComImport(), + Guid("B196B288-BAB4-101A-B69C-00AA00341D07"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IOleControl { + + + [PreserveSig] + int GetControlInfo( + [Out] + NativeMethods.tagCONTROLINFO pCI); + + [PreserveSig] + int OnMnemonic( + [In] + ref System.Windows.Interop.MSG pMsg); + + [PreserveSig] + int OnAmbientPropertyChange( + + int dispID); + + [PreserveSig] + int FreezeEvents( + + int bFreeze); + + } + + /// + /// Critical - elevates via a SUC. + /// + [SecurityCritical( SecurityCriticalScope.Everything ) , SuppressUnmanagedCodeSecurity ] + [ComImport(), + Guid("B196B286-BAB4-101A-B69C-00AA00341D07"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IConnectionPoint { + + [PreserveSig] + int GetConnectionInterface(out Guid iid); + + + [PreserveSig] + int GetConnectionPointContainer( + [MarshalAs(UnmanagedType.Interface)] + ref IConnectionPointContainer pContainer); + + + [PreserveSig] + int Advise( + [In, MarshalAs(UnmanagedType.Interface)] + object pUnkSink, + ref int cookie); + + + [PreserveSig] + int Unadvise( + + int cookie); + + [PreserveSig] + int EnumConnections(out object pEnum); + + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("00020404-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IEnumVariant { + /// + /// Critical: This code elevates to call unmanaged code + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [PreserveSig] + int Next( + [In, MarshalAs(UnmanagedType.U4)] + int celt, + [In, Out] + IntPtr rgvar, + [Out, MarshalAs(UnmanagedType.LPArray)] + int[] pceltFetched); + + void Skip( + [In, MarshalAs(UnmanagedType.U4)] + int celt); + + /// + /// Critical: This code elevates to call unmanaged code + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + void Reset(); + + void Clone( + [Out, MarshalAs(UnmanagedType.LPArray)] + UnsafeNativeMethods.IEnumVariant[] ppenum); + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("00000104-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IEnumOLEVERB { + + + [PreserveSig] + int Next( + [MarshalAs(UnmanagedType.U4)] + int celt, + [Out] + NativeMethods.tagOLEVERB rgelt, + [Out, MarshalAs(UnmanagedType.LPArray)] + int[] pceltFetched); + + [PreserveSig] + int Skip( + [In, MarshalAs(UnmanagedType.U4)] + int celt); + + + void Reset(); + + + void Clone( + out IEnumOLEVERB ppenum); + + + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + // This interface has different parameter marshaling from System.Runtime.InteropServices.ComTypes.IStream. + // They are incompatable. But type cast will succeed because they have the same guid. + [ComImport(), Guid("0000000C-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IStream { + + int Read( + + IntPtr buf, + + int len); + + + int Write( + + IntPtr buf, + + int len); + + [return: MarshalAs(UnmanagedType.I8)] + long Seek( + [In, MarshalAs(UnmanagedType.I8)] + long dlibMove, + + int dwOrigin); + + + void SetSize( + [In, MarshalAs(UnmanagedType.I8)] + long libNewSize); + + [return: MarshalAs(UnmanagedType.I8)] + long CopyTo( + [In, MarshalAs(UnmanagedType.Interface)] + UnsafeNativeMethods.IStream pstm, + [In, MarshalAs(UnmanagedType.I8)] + long cb, + [Out, MarshalAs(UnmanagedType.LPArray)] + long[] pcbRead); + + + void Commit( + + int grfCommitFlags); + + + void Revert(); + + + void LockRegion( + [In, MarshalAs(UnmanagedType.I8)] + long libOffset, + [In, MarshalAs(UnmanagedType.I8)] + long cb, + + int dwLockType); + + + void UnlockRegion( + [In, MarshalAs(UnmanagedType.I8)] + long libOffset, + [In, MarshalAs(UnmanagedType.I8)] + long cb, + + int dwLockType); + + + void Stat( + [Out] + NativeMethods.STATSTG pStatstg, + int grfStatFlag); + + [return: MarshalAs(UnmanagedType.Interface)] + UnsafeNativeMethods.IStream Clone(); + } + + + /// + /// Critical - elevates via a SUC. + /// + [SecurityCritical( SecurityCriticalScope.Everything ) , SuppressUnmanagedCodeSecurity ] + [ComImport(), + Guid("B196B284-BAB4-101A-B69C-00AA00341D07"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IConnectionPointContainer + { + + [return: MarshalAs(UnmanagedType.Interface)] + object EnumConnectionPoints(); + + [PreserveSig] + int FindConnectionPoint([In] ref Guid guid, [Out, MarshalAs(UnmanagedType.Interface)]out IConnectionPoint ppCP); + + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("B196B285-BAB4-101A-B69C-00AA00341D07"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IEnumConnectionPoints { + [PreserveSig] + int Next(int cConnections, out IConnectionPoint pCp, out int pcFetched); + + [PreserveSig] + int Skip(int cSkip); + + void Reset(); + + IEnumConnectionPoints Clone(); + } + +#if !DRT && !UIAUTOMATIONTYPES + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("00020400-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IDispatch { + + #region + + int GetTypeInfoCount(); + + [return: MarshalAs(UnmanagedType.Interface)] + ITypeInfo GetTypeInfo( + [In, MarshalAs(UnmanagedType.U4)] + int iTInfo, + [In, MarshalAs(UnmanagedType.U4)] + int lcid); + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [PreserveSig] + HR GetIDsOfNames( + [In] + ref Guid riid, + [In, MarshalAs(UnmanagedType.LPArray)] + string[] rgszNames, + [In, MarshalAs(UnmanagedType.U4)] + int cNames, + [In, MarshalAs(UnmanagedType.U4)] + int lcid, + [Out, MarshalAs(UnmanagedType.LPArray)] + int[] rgDispId); + + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [PreserveSig] + HR Invoke( + + int dispIdMember, + [In] + ref Guid riid, + [In, MarshalAs(UnmanagedType.U4)] + int lcid, + [In, MarshalAs(UnmanagedType.U4)] + int dwFlags, + [Out, In] + NativeMethods.DISPPARAMS pDispParams, + [Out] + out object pVarResult, + [Out, In] + NativeMethods.EXCEPINFO pExcepInfo, + [Out, MarshalAs(UnmanagedType.LPArray)] + IntPtr [] pArgErr); + + #endregion + + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("A6EF9860-C720-11D0-9337-00A0C90DCAA9"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IDispatchEx : IDispatch { + + #region + + new int GetTypeInfoCount(); + + [return: MarshalAs(UnmanagedType.Interface)] + new ITypeInfo GetTypeInfo( + [In, MarshalAs(UnmanagedType.U4)] + int iTInfo, + [In, MarshalAs(UnmanagedType.U4)] + int lcid); + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [PreserveSig] + new HR GetIDsOfNames( + [In] + ref Guid riid, + [In, MarshalAs(UnmanagedType.LPArray)] + string[] rgszNames, + [In, MarshalAs(UnmanagedType.U4)] + int cNames, + [In, MarshalAs(UnmanagedType.U4)] + int lcid, + [Out, MarshalAs(UnmanagedType.LPArray)] + int[] rgDispId); + + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [PreserveSig] + new HR Invoke( + int dispIdMember, + [In] + ref Guid riid, + [In, MarshalAs(UnmanagedType.U4)] + int lcid, + [In, MarshalAs(UnmanagedType.U4)] + int dwFlags, + [Out, In] + NativeMethods.DISPPARAMS pDispParams, + [Out] + out object pVarResult, + [Out, In] + NativeMethods.EXCEPINFO pExcepInfo, + [Out, MarshalAs(UnmanagedType.LPArray)] + IntPtr [] pArgErr); + + #endregion + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [PreserveSig] + HR GetDispID( + string name, + int nameProperties, + [Out] out int dispId); + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [PreserveSig] + HR InvokeEx( + int dispId, + [MarshalAs(UnmanagedType.U4)] int lcid, + [MarshalAs(UnmanagedType.U4)] int flags, + [In, Out] NativeMethods.DISPPARAMS dispParams, + [Out] out object result, + /* COM interop caveat: Declaring the following just as Out seems to cause + garbage being handed out for the native buffer (it's out anyway). Upon + returning from the COM call, CLR copies back to the managed object but + chokes on the garbage string pointers trying to do memcpy, causing AV. + See also Dev10 work item 730339 to fix this in the CLR, by zeroing out + the memory that's handed over to native code in this circumstance. */ + [In, Out] NativeMethods.EXCEPINFO exceptionInfo, + IServiceProvider serviceProvider); + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void DeleteMemberByName(string name, int flags); + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void DeleteMemberByDispID(int dispId); + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + int GetMemberProperties(int dispId, int propFlags); + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + string GetMemberName(int dispId); + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + int GetNextDispID(int enumFlags, int dispId); + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [return: MarshalAs(UnmanagedType.IUnknown)] + object GetNameSpaceParent(); + + } + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IServiceProvider { + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [return: MarshalAs(UnmanagedType.IUnknown)] + object QueryService(ref Guid service, ref Guid riid); + + } + +#endif + + #region WebBrowser Related Definitions + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E"), + TypeLibType(TypeLibTypeFlags.FHidden | TypeLibTypeFlags.FDual | TypeLibTypeFlags.FOleAutomation)] + public interface IWebBrowser2 + { + // + // IWebBrowser members + + /// + /// Critical elevates via a SUC. + /// + [DispId(100)] + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void GoBack(); + + /// + /// Critical elevates via a SUC. + /// + [DispId(101)] + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void GoForward(); + + [DispId(102)] + void GoHome(); + [DispId(103)] + void GoSearch(); + [DispId(104)] + void Navigate([In] string Url, [In] ref object flags, + [In] ref object targetFrameName, [In] ref object postData, + [In] ref object headers); + + /// + /// Critical elevates via a SUC. + /// + [DispId(-550)] + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void Refresh(); + + /// + /// Critical elevates via a SUC. + /// + [DispId(105)] + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void Refresh2([In] ref object level); + + [DispId(106)] + void Stop(); + [DispId(200)] + object Application { [return: MarshalAs(UnmanagedType.IDispatch)]get;} + [DispId(201)] + object Parent { [return: MarshalAs(UnmanagedType.IDispatch)]get;} + [DispId(202)] + object Container { [return: MarshalAs(UnmanagedType.IDispatch)]get;} + + /// + /// Critical elevates via a SUC. + /// + [DispId(203)] + object Document { [return: MarshalAs(UnmanagedType.IDispatch)] + [SuppressUnmanagedCodeSecurity, SecurityCritical] + get;} + + [DispId(204)] + bool TopLevelContainer { get;} + [DispId(205)] + string Type { get;} + [DispId(206)] + int Left { get; set;} + [DispId(207)] + int Top { get; set;} + [DispId(208)] + int Width { get; set;} + [DispId(209)] + int Height { get; set;} + [DispId(210)] + string LocationName { get;} + + /// + /// Critical elevates via a SUC. + /// + [DispId(211)] + string LocationURL { + [SuppressUnmanagedCodeSecurity, SecurityCritical] + get;} + + [DispId(212)] + bool Busy { get;} + // + // IWebBrowserApp members + [DispId(300)] + void Quit(); + [DispId(301)] + void ClientToWindow([Out]out int pcx, [Out]out int pcy); + [DispId(302)] + void PutProperty([In] string property, [In] object vtValue); + [DispId(303)] + object GetProperty([In] string property); + [DispId(0)] + string Name { get;} + [DispId(-515)] + int HWND { get;} + [DispId(400)] + string FullName { get;} + [DispId(401)] + string Path { get;} + [DispId(402)] + bool Visible { get; set;} + [DispId(403)] + bool StatusBar { get; set;} + [DispId(404)] + string StatusText { get; set;} + [DispId(405)] + int ToolBar { get; set;} + [DispId(406)] + bool MenuBar { get; set;} + [DispId(407)] + bool FullScreen { get; set;} + + // + // IWebBrowser2 members + /// + /// Critical elevates via a SUC. + /// + [DispId(500)] + [SuppressUnmanagedCodeSecurity, SecurityCritical ] + void Navigate2([In] ref object URL, [In] ref object flags, + [In] ref object targetFrameName, [In] ref object postData, + [In] ref object headers); + + [DispId(501)] + UnsafeNativeMethods.OLECMDF QueryStatusWB([In] UnsafeNativeMethods.OLECMDID cmdID); + [DispId(502)] + void ExecWB([In] UnsafeNativeMethods.OLECMDID cmdID, + [In] UnsafeNativeMethods.OLECMDEXECOPT cmdexecopt, + ref object pvaIn, + IntPtr pvaOut); + [DispId(503)] + void ShowBrowserBar([In] ref object pvaClsid, [In] ref object pvarShow, + [In] ref object pvarSize); + [DispId(-525)] + NativeMethods.WebBrowserReadyState ReadyState { get;} + [DispId(550)] + bool Offline { get; set;} + [DispId(551)] + bool Silent { get; set;} + [DispId(552)] + bool RegisterAsBrowser { get; set;} + [DispId(553)] + bool RegisterAsDropTarget { get; set;} + [DispId(554)] + bool TheaterMode { get; set;} + [DispId(555)] + bool AddressBar { get; set;} + [DispId(556)] + bool Resizable { get; set;} + } + + [ComImport(), Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch), + TypeLibType(TypeLibTypeFlags.FHidden)] + public interface DWebBrowserEvents2 + { + [DispId(102)] + void StatusTextChange([In] string text); + [DispId(108)] + void ProgressChange([In] int progress, [In] int progressMax); + [DispId(105)] + void CommandStateChange([In] long command, [In] bool enable); + [DispId(106)] + void DownloadBegin(); + [DispId(104)] + void DownloadComplete(); + [DispId(113)] + void TitleChange([In] string text); + [DispId(112)] + void PropertyChange([In] string szProperty); + [DispId(225)] + void PrintTemplateInstantiation([In, MarshalAs(UnmanagedType.IDispatch)] object pDisp); + [DispId(226)] + void PrintTemplateTeardown([In, MarshalAs(UnmanagedType.IDispatch)] object pDisp); + [DispId(227)] + void UpdatePageStatus([In, MarshalAs(UnmanagedType.IDispatch)] object pDisp, + [In] ref object nPage, [In] ref object fDone); + [DispId(250)] + void BeforeNavigate2([In, MarshalAs(UnmanagedType.IDispatch)] object pDisp, + [In] ref object URL, [In] ref object flags, + [In] ref object targetFrameName, [In] ref object postData, + [In] ref object headers, [In, Out] ref bool cancel); + [DispId(251)] + void NewWindow2([In, Out, MarshalAs(UnmanagedType.IDispatch)] ref object pDisp, + [In, Out] ref bool cancel); + [DispId(252)] + void NavigateComplete2([In, MarshalAs(UnmanagedType.IDispatch)] object pDisp, + [In] ref object URL); + [DispId(259)] + void DocumentComplete([In, MarshalAs(UnmanagedType.IDispatch)] object pDisp, + [In] ref object URL); + [DispId(253)] + void OnQuit(); + [DispId(254)] + void OnVisible([In] bool visible); + [DispId(255)] + void OnToolBar([In] bool toolBar); + [DispId(256)] + void OnMenuBar([In] bool menuBar); + [DispId(257)] + void OnStatusBar([In] bool statusBar); + [DispId(258)] + void OnFullScreen([In] bool fullScreen); + [DispId(260)] + void OnTheaterMode([In] bool theaterMode); + [DispId(262)] + void WindowSetResizable([In] bool resizable); + [DispId(264)] + void WindowSetLeft([In] int left); + [DispId(265)] + void WindowSetTop([In] int top); + [DispId(266)] + void WindowSetWidth([In] int width); + [DispId(267)] + void WindowSetHeight([In] int height); + [DispId(263)] + void WindowClosing([In] bool isChildWindow, [In, Out] ref bool cancel); + [DispId(268)] + void ClientToHostWindow([In, Out] ref long cx, [In, Out] ref long cy); + [DispId(269)] + void SetSecureLockIcon([In] int secureLockIcon); + [DispId(270)] + void FileDownload([In, Out] ref bool ActiveDocument, [In, Out] ref bool cancel); + [DispId(271)] + void NavigateError([In, MarshalAs(UnmanagedType.IDispatch)] object pDisp, + [In] ref object URL, [In] ref object frame, [In] ref object statusCode, [In, Out] ref bool cancel); + [DispId(272)] + void PrivacyImpactedStateChange([In] bool bImpacted); + [DispId(282)] // IE 7+ + void SetPhishingFilterStatus(uint phishingFilterStatus); + [DispId(283)] // IE 7+ + void WindowStateChanged(uint dwFlags, uint dwValidFlagsMask); + } + + + // Used to control the webbrowser appearance and provide DTE to script via window.external + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ ComImport(), Guid("BD3F23C0-D43E-11CF-893B-00AA00BDCE1A"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IDocHostUIHandler + { + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int ShowContextMenu( + [In, MarshalAs(UnmanagedType.U4)] + int dwID, + [In] + NativeMethods.POINT pt, + [In, MarshalAs(UnmanagedType.Interface)] + object pcmdtReserved, + [In, MarshalAs(UnmanagedType.Interface)] + object pdispReserved); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int GetHostInfo( + [In, Out] + NativeMethods.DOCHOSTUIINFO info); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int ShowUI( + [In, MarshalAs(UnmanagedType.I4)] + int dwID, + [In] + UnsafeNativeMethods.IOleInPlaceActiveObject activeObject, + [In] + NativeMethods.IOleCommandTarget commandTarget, + [In] + UnsafeNativeMethods.IOleInPlaceFrame frame, + [In] + UnsafeNativeMethods.IOleInPlaceUIWindow doc); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int HideUI(); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int UpdateUI(); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int EnableModeless( + [In, MarshalAs(UnmanagedType.Bool)] + bool fEnable); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int OnDocWindowActivate( + [In, MarshalAs(UnmanagedType.Bool)] + bool fActivate); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int OnFrameWindowActivate( + [In, MarshalAs(UnmanagedType.Bool)] + bool fActivate); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int ResizeBorder( + [In] + NativeMethods.COMRECT rect, + [In] + UnsafeNativeMethods.IOleInPlaceUIWindow doc, + bool fFrameWindow); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int TranslateAccelerator( + [In] + ref System.Windows.Interop.MSG msg, + [In] + ref Guid group, + [In, MarshalAs(UnmanagedType.I4)] + int nCmdID); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int GetOptionKeyPath( + [Out, MarshalAs(UnmanagedType.LPArray)] + String[] pbstrKey, + [In, MarshalAs(UnmanagedType.U4)] + int dw); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int GetDropTarget( + [In, MarshalAs(UnmanagedType.Interface)] + UnsafeNativeMethods.IOleDropTarget pDropTarget, + [Out, MarshalAs(UnmanagedType.Interface)] + out UnsafeNativeMethods.IOleDropTarget ppDropTarget); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int GetExternal( + [Out, MarshalAs(UnmanagedType.IDispatch)] + out object ppDispatch); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int TranslateUrl( + [In, MarshalAs(UnmanagedType.U4)] + int dwTranslate, + [In, MarshalAs(UnmanagedType.LPWStr)] + string strURLIn, + [Out, MarshalAs(UnmanagedType.LPWStr)] + out string pstrURLOut); + + [return: MarshalAs(UnmanagedType.I4)] + [PreserveSig] + int FilterDataObject( + IComDataObject pDO, + out IComDataObject ppDORet); + + + } + + /// + /// Critical: elevates via SUC. + /// + [ComImport, Guid("3050F21F-98B5-11CF-BB82-00AA00BDCE0B"), InterfaceType(ComInterfaceType.InterfaceIsDual)] + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + internal interface IHTMLElementCollection + { + string toString(); + void SetLength(int p); + int GetLength(); + [return: MarshalAs(UnmanagedType.Interface)] + object Get_newEnum(); + [return: MarshalAs(UnmanagedType.IDispatch)] + object Item(object idOrName, object index); + [return: MarshalAs(UnmanagedType.Interface)] + object Tags(object tagName); + }; + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport, Guid("626FC520-A41E-11CF-A731-00A0C9082637"), InterfaceType(ComInterfaceType.InterfaceIsDual)] + internal interface IHTMLDocument + { + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [return: MarshalAs(UnmanagedType.IDispatch)] + object GetScript(); + + } + + /// + /// Critical: elevates via SUC. + /// If the document is not cross-domain relative to the host application, all methods on this interface + /// can be considered 'safe for scripting'. + /// + [ComImport, Guid("332C4425-26CB-11D0-B483-00C04FD90119"), InterfaceType(ComInterfaceType.InterfaceIsDual)] + [SuppressUnmanagedCodeSecurity, SecurityCritical(SecurityCriticalScope.Everything)] + internal interface IHTMLDocument2: IHTMLDocument + { + #region IHTMLDocument - base interface + [return: MarshalAs(UnmanagedType.Interface)] + new object GetScript(); + #endregion + IHTMLElementCollection GetAll(); + [return: MarshalAs(UnmanagedType.Interface)] + /*IHTMLElement*/object GetBody(); + [return: MarshalAs(UnmanagedType.Interface)] + /*IHTMLElement*/object GetActiveElement(); + IHTMLElementCollection GetImages(); + IHTMLElementCollection GetApplets(); + IHTMLElementCollection GetLinks(); + IHTMLElementCollection GetForms(); + IHTMLElementCollection GetAnchors(); + void SetTitle(string p); + string GetTitle(); + IHTMLElementCollection GetScripts(); + void SetDesignMode(string p); + string GetDesignMode(); + [return: MarshalAs(UnmanagedType.Interface)] + object GetSelection(); + string GetReadyState(); + [return: MarshalAs(UnmanagedType.Interface)] + object GetFrames(); + IHTMLElementCollection GetEmbeds(); + IHTMLElementCollection GetPlugins(); + void SetAlinkColor(object c); + object GetAlinkColor(); + void SetBgColor(object c); + object GetBgColor(); + void SetFgColor(object c); + object GetFgColor(); + void SetLinkColor(object c); + object GetLinkColor(); + void SetVlinkColor(object c); + object GetVlinkColor(); + string GetReferrer(); + IHTMLLocation GetLocation(); + string GetLastModified(); + void SetUrl(string p); + string GetUrl(); + void SetDomain(string p); + string GetDomain(); + void SetCookie(string p); + string GetCookie(); + void SetExpando(bool p); + bool GetExpando(); + void SetCharset(string p); + string GetCharset(); + void SetDefaultCharset(string p); + string GetDefaultCharset(); + string GetMimeType(); + string GetFileSize(); + string GetFileCreatedDate(); + string GetFileModifiedDate(); + string GetFileUpdatedDate(); + string GetSecurity(); + string GetProtocol(); + string GetNameProp(); + int Write([In, MarshalAs(UnmanagedType.SafeArray)] object[] psarray); + int WriteLine([In, MarshalAs(UnmanagedType.SafeArray)] object[] psarray); + [return: MarshalAs(UnmanagedType.Interface)] + object Open(string mimeExtension, object name, object features, object replace); + void Close(); + void Clear(); + bool QueryCommandSupported(string cmdID); + bool QueryCommandEnabled(string cmdID); + bool QueryCommandState(string cmdID); + bool QueryCommandIndeterm(string cmdID); + string QueryCommandText(string cmdID); + object QueryCommandValue(string cmdID); + bool ExecCommand(string cmdID, bool showUI, object value); + bool ExecCommandShowHelp(string cmdID); + [return: MarshalAs(UnmanagedType.Interface)] + /*IHTMLElement*/object CreateElement(string eTag); + void SetOnhelp(object p); + object GetOnhelp(); + void SetOnclick(object p); + object GetOnclick(); + void SetOndblclick(object p); + object GetOndblclick(); + void SetOnkeyup(object p); + object GetOnkeyup(); + void SetOnkeydown(object p); + object GetOnkeydown(); + void SetOnkeypress(object p); + object GetOnkeypress(); + void SetOnmouseup(object p); + object GetOnmouseup(); + void SetOnmousedown(object p); + object GetOnmousedown(); + void SetOnmousemove(object p); + object GetOnmousemove(); + void SetOnmouseout(object p); + object GetOnmouseout(); + void SetOnmouseover(object p); + object GetOnmouseover(); + void SetOnreadystatechange(object p); + object GetOnreadystatechange(); + void SetOnafterupdate(object p); + object GetOnafterupdate(); + void SetOnrowexit(object p); + object GetOnrowexit(); + void SetOnrowenter(object p); + object GetOnrowenter(); + void SetOndragstart(object p); + object GetOndragstart(); + void SetOnselectstart(object p); + object GetOnselectstart(); + [return: MarshalAs(UnmanagedType.Interface)] + /*IHTMLElement*/object ElementFromPoint(int x, int y); + [return: MarshalAs(UnmanagedType.Interface)] + /*IHTMLWindow2*/object GetParentWindow(); + [return: MarshalAs(UnmanagedType.Interface)] + object GetStyleSheets(); + void SetOnbeforeupdate(object p); + object GetOnbeforeupdate(); + void SetOnerrorupdate(object p); + object GetOnerrorupdate(); + string toString(); + [return: MarshalAs(UnmanagedType.Interface)] + object CreateStyleSheet(string bstrHref, int lIndex); + }; + + /// + /// Critical: elevates via SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsDual), Guid("163BB1E0-6E00-11CF-837A-48DC04C10000")] + internal interface IHTMLLocation + { + void SetHref(string p); + string GetHref(); + void SetProtocol(string p); + string GetProtocol(); + void SetHost(string p); + string GetHost(); + void SetHostname(string p); + string GetHostname(); + void SetPort(string p); + string GetPort(); + void SetPathname(string p); + string GetPathname(); + void SetSearch(string p); + string GetSearch(); + void SetHash(string p); + string GetHash(); + void Reload(bool flag); + void Replace(string bstr); + void Assign(string bstr); + }; + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport, Guid("3050f6cf-98b5-11cf-bb82-00aa00bdce0b"), InterfaceType(ComInterfaceType.InterfaceIsDual)] + internal interface IHTMLWindow4 + { + [return: MarshalAs(UnmanagedType.IDispatch)] object CreatePopup([In] ref object reserved); + [return: MarshalAs(UnmanagedType.Interface)] object frameElement(); + } + + internal static class ArrayToVARIANTHelper + { + /// + /// Critical - Calls Marshal.OffsetOf(), which has a LinkDemand for unmanaged code. + /// TreatAsSafe - This is not exploitable. + /// + [SecurityCritical, SecurityTreatAsSafe] + static ArrayToVARIANTHelper() + { + VariantSize = (int)Marshal.OffsetOf(typeof(FindSizeOfVariant), "b"); + } + + // Convert a object[] into an array of VARIANT, allocated with CoTask allocators. + /// + /// Critical: Calls Marshal.GetNativeVariantForObject(), which has a LinkDemand for unmanaged code. + /// + [SecurityCritical] + public unsafe static IntPtr ArrayToVARIANTVector(object[] args) + { + IntPtr mem = IntPtr.Zero; + int i = 0; + try + { + checked + { + int len = args.Length; + mem = Marshal.AllocCoTaskMem(len * VariantSize); + byte* a = (byte*)(void*)mem; + for (i = 0; i < len; ++i) + { + Marshal.GetNativeVariantForObject(args[i], (IntPtr)(a + VariantSize * i)); + } + } + } + catch + { + if (mem != IntPtr.Zero) + { + FreeVARIANTVector(mem, i); + } + throw; + } + return mem; + } + + // Free a Variant array created with the above function + /// + /// Critical: Calls Marshal.FreeCoTaskMem(), which has a LinkDemand for unmanaged code. + /// + /// The allocated memory to be freed. + /// The length of the Variant vector to be cleared. + [SecurityCritical] + public unsafe static void FreeVARIANTVector(IntPtr mem, int len) + { + int hr = NativeMethods.S_OK; + byte* a = (byte*)(void*)mem; + + for (int i = 0; i < len; ++i) + { + int hrcurrent = NativeMethods.S_OK; + checked + { + hrcurrent = UnsafeNativeMethods.VariantClear((IntPtr)(a + VariantSize * i)); + } + + // save the first error and throw after we finish all VariantClear. + if (NativeMethods.Succeeded(hr) && NativeMethods.Failed(hrcurrent)) + { + hr = hrcurrent; + } + } + Marshal.FreeCoTaskMem(mem); + + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + private struct FindSizeOfVariant + { + [MarshalAs(UnmanagedType.Struct)] + public object var; + public byte b; + } + + private static readonly int VariantSize; + } + + /// + /// Critical - This code causes unmanaged code elevation. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport(ExternDll.Oleaut32, PreserveSig=true)] + private static extern int VariantClear(IntPtr pObject); + + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport(), Guid("7FD52380-4E07-101B-AE2D-08002B2EC713"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IPersistStreamInit + { + void GetClassID( + [Out] + out Guid pClassID); + + [PreserveSig] + int IsDirty(); + + /// + /// Critical elevates via a SUC. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void Load( + [In, MarshalAs(UnmanagedType.Interface)] + System.Runtime.InteropServices.ComTypes.IStream pstm); + + void Save( + [In, MarshalAs(UnmanagedType.Interface)] + IStream pstm, + [In, MarshalAs(UnmanagedType.Bool)] + bool fClearDirty); + + void GetSizeMax( + [Out, MarshalAs(UnmanagedType.LPArray)] + long pcbSize); + + void InitNew(); + } + + [Flags] + internal enum BrowserNavConstants : uint + { + OpenInNewWindow = 0x00000001, + NoHistory = 0x00000002, + NoReadFromCache = 0x00000004, + NoWriteToCache = 0x00000008, + AllowAutosearch = 0x00000010, + BrowserBar = 0x00000020, + Hyperlink = 0x00000040, + EnforceRestricted = 0x00000080, + NewWindowsManaged = 0x00000100, + UntrustedForDownload = 0x00000200, + TrustedForActiveX = 0x00000400, + OpenInNewTab = 0x00000800, + OpenInBackgroundTab = 0x00001000, + KeepWordWheelText = 0x00002000 + } +#if never + // + // Used to control the webbrowser security + /// + /// Critical:Elevates to Unmanaged code permission + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComVisible(true), ComImport(), Guid("79eac9ee-baf9-11ce-8c82-00aa004ba90b"), + InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown), CLSCompliant(false)] + public interface IInternetSecurityManager { + [PreserveSig] int SetSecuritySite(); + [PreserveSig] int GetSecuritySite(); + [PreserveSig] int MapUrlToZone(); + [PreserveSig] int GetSecurityId(); + [PreserveSig] int ProcessUrlAction(string url, int action, + [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] byte[] policy, + int cbPolicy, ref byte context, int cbContext, + int flags, int reserved); + [PreserveSig] int QueryCustomPolicy(); + [PreserveSig] int SetZoneMapping(); + [PreserveSig] int GetZoneMappings(); + } +#endif + #endregion WebBrowser Related Definitions + + /// + /// Critical: as suppressing UnmanagedCodeSecurity + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError=true, CharSet=CharSet.Auto)] + public static extern uint GetRawInputDeviceList( + [In, Out] NativeMethods.RAWINPUTDEVICELIST[] ridl, + [In, Out] ref uint numDevices, + uint sizeInBytes); + + /// + /// Critical: as suppressing UnmanagedCodeSecurity + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError=true, CharSet=CharSet.Auto)] + public static extern uint GetRawInputDeviceInfo( + IntPtr hDevice, + uint command, + [In] ref NativeMethods.RID_DEVICE_INFO ridInfo, + ref uint sizeInBytes); + + + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCompiler.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCompiler.cs new file mode 100644 index 00000000000..709e4f3cda0 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCompiler.cs @@ -0,0 +1,60 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +using System; +using System.Text; +using System.ComponentModel; +using System.Security; +using System.Security.Permissions; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; + +namespace MS.Win32.Compile +{ + + // + // Keep unsafe native methods used by Compiler related classes. + // It can be shared by PresentationBuildTasks and PresentationFramework + // +#if !PBTCOMPILER + [MS.Internal.PresentationCore.FriendAccessAllowed] // Used by both PBT and PresentationFramework +#endif + internal static partial class UnsafeNativeMethods { + + //------------------------------------------------------ + // + // Internal Methods + // + //------------------------------------------------------ + + #region internal Methods + +#if !PBTCOMPILER + [DllImport(ExternDll.Shfolder, CharSet = CharSet.Auto, BestFitMapping = false)] + public static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, int dwFlags, StringBuilder lpszPath); +#endif + + /// + /// Critical: This code calls into unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("urlmon.dll", CharSet = CharSet.Unicode)] + internal static extern int FindMimeFromData( + IBindCtx pBC, // bind context - can be NULL + string wszUrl, // url - can be null + IntPtr Buffer, // buffer with data to sniff - + // can be null (pwzUrl must be valid) + int cbSize, // size of buffer + string wzMimeProposed, // proposed mime if - can be null + int dwMimeFlags, // will be determined + out string wzMimeOut, // the suggested mime + int dwReserved); + + #endregion + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsEventTrace.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsEventTrace.cs new file mode 100644 index 00000000000..b4b4a35e3f7 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsEventTrace.cs @@ -0,0 +1,261 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ +// +#if !SILVERLIGHTXAML + +using System; +using System.Security; +using System.Runtime.InteropServices; +#if SYSTEM_XAML +using MS.Internal.Xaml; +#else +using MS.Utility; +#endif + +namespace MS.Win32 +{ + // + // ETW Tracing native methods + // + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + internal static unsafe class ManifestEtw + { + // + // ETW Methods + // + // + // Callback + // + /// + /// Critical - Accepts untrusted pointer argument + /// + [SecurityCritical] + internal unsafe delegate void EtwEnableCallback( + [In] ref Guid sourceId, + [In] int isEnabled, + [In] byte level, + [In] long matchAnyKeywords, + [In] long matchAllKeywords, + [In] EVENT_FILTER_DESCRIPTOR* filterData, + [In] void* callbackContext + ); + + // + // Registration APIs + // + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("Advapi32.dll", ExactSpelling = true, EntryPoint = "EventRegister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] + internal static extern unsafe uint EventRegister( + [In] ref Guid providerId, + [In]EtwEnableCallback enableCallback, + [In]void* callbackContext, + [In][Out]ref ulong registrationHandle + ); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("Advapi32.dll", ExactSpelling = true, EntryPoint = "EventUnregister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] + internal static extern uint EventUnregister([In] ulong registrationHandle); + + // + // Writing (Publishing/Logging) APIs + // + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("Advapi32.dll", ExactSpelling = true, EntryPoint = "EventWrite", CharSet = System.Runtime.InteropServices.CharSet.Unicode)] + internal static extern unsafe uint EventWrite( + [In] ulong registrationHandle, + [In] ref EventDescriptor eventDescriptor, + [In] uint userDataCount, + [In] EventData* userData + ); + + [StructLayout(LayoutKind.Sequential)] + unsafe internal struct EVENT_FILTER_DESCRIPTOR + { + public long Ptr; + public int Size; + public int Type; + }; + + + [StructLayout(LayoutKind.Explicit, Size = 16)] + internal struct EventDescriptor + { + [FieldOffset(0)] + internal ushort Id; + [FieldOffset(2)] + internal byte Version; + [FieldOffset(3)] + internal byte Channel; + [FieldOffset(4)] + internal byte Level; + [FieldOffset(5)] + internal byte Opcode; + [FieldOffset(6)] + internal ushort Task; + [FieldOffset(8)] + internal long Keywords; + } + } + + [SuppressUnmanagedCodeSecurity] + internal static unsafe class ClassicEtw + { + #region RegisterTraceGuidsW() + // Support structs for RegisterTraceGuidsW + [StructLayout(LayoutKind.Sequential)] + internal struct TRACE_GUID_REGISTRATION + { + /// + /// Critical: Pointer field + /// + [SecurityCritical] + internal unsafe Guid* Guid; + + /// + /// Critical: Pointer field + /// + [SecurityCritical] + internal unsafe void* RegHandle; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct WNODE_HEADER + { + public UInt32 BufferSize; + public UInt32 ProviderId; + public UInt64 HistoricalContext; + public UInt64 TimeStamp; + public Guid Guid; + public UInt32 ClientContext; + public UInt32 Flags; + }; + + + internal enum WMIDPREQUESTCODE + { + GetAllData = 0, + GetSingleInstance = 1, + SetSingleInstance = 2, + SetSingleItem = 3, + EnableEvents = 4, + DisableEvents = 5, + EnableCollection = 6, + DisableCollection = 7, + RegInfo = 8, + ExecuteMethod = 9, + }; + + /// + /// Critical: Delegate that takes an unsafe pointer argument + /// + [SecurityCritical] + internal unsafe delegate uint ControlCallback(WMIDPREQUESTCODE requestCode, IntPtr requestContext, IntPtr reserved, WNODE_HEADER* data); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("Advapi32.dll", CharSet = CharSet.Unicode)] + internal static extern uint RegisterTraceGuidsW([In] ControlCallback cbFunc, [In] IntPtr context, [In] ref Guid providerGuid, [In] int taskGuidCount, [In, Out] ref TRACE_GUID_REGISTRATION taskGuids, [In] string mofImagePath, [In] string mofResourceName, out ulong regHandle); + #endregion // RegisterTraceGuidsW + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("Advapi32.dll")] + internal static extern uint UnregisterTraceGuids(ulong regHandle); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("Advapi32.dll")] + internal static extern int GetTraceEnableFlags(ulong traceHandle); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("Advapi32.dll")] + internal static extern byte GetTraceEnableLevel(ulong traceHandle); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("Advapi32.dll")] + internal static extern long GetTraceLoggerHandle(WNODE_HEADER* data); + + #region TraceEvent() + // Structures for TraceEvent API. + + // Constants for flags field. + internal const int WNODE_FLAG_TRACED_GUID = 0x00020000; + internal const int WNODE_FLAG_USE_MOF_PTR = 0x00100000; + + // Size is 48 = 0x30 bytes; + [StructLayout(LayoutKind.Sequential)] + internal struct EVENT_TRACE_HEADER + { + public ushort Size; + public ushort FieldTypeFlags; // holds our MarkerFlags too + public byte Type; // This is now called opcode. + public byte Level; + public ushort Version; + public int ThreadId; + public int ProcessId; + public long TimeStamp; // Offset 0x10 + public Guid Guid; // Offset 0x18 + public uint ClientContext; // Offset 0x28 + public uint Flags; // Offset 0x2C + } + + internal const int MAX_MOF_FIELDS = 16; + [StructLayout(LayoutKind.Explicit, Size = 48 + 16 * MAX_MOF_FIELDS)] + internal struct EVENT_HEADER + { + [FieldOffset(0)] + public EVENT_TRACE_HEADER Header; + [FieldOffset(48)] + public EventData Data; // Actually variable sized; + } + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("Advapi32.dll")] + internal static extern unsafe uint TraceEvent(ulong traceHandle, EVENT_HEADER* header); + #endregion // TraceEvent() + } +} + +#endif //!SILVERLIGHTXAML + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsOther.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsOther.cs new file mode 100644 index 00000000000..87554cdce98 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsOther.cs @@ -0,0 +1,1632 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +using System.Threading; +using System.ComponentModel; +using System.Diagnostics; + +namespace MS.Win32 +{ + using Accessibility; + using SRCS = System.Runtime.CompilerServices; + using System.Runtime.ConstrainedExecution; + using System.Runtime.InteropServices; + using System; + using System.Security.Permissions; + using System.Collections; + using System.IO; + using System.Text; + using System.Security; + using Microsoft.Win32.SafeHandles; + using MS.Internal; + using MS.Internal.Interop; + using MS.Utility; + +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif DRT + using MS.Internal.Drt; +#else +#error Attempt to use FriendAccessAllowedAttribute from an unknown assembly. + using MS.Internal.YourAssemblyName; +#endif + + using IComDataObject = System.Runtime.InteropServices.ComTypes.IDataObject; + + //[SuppressUnmanagedCodeSecurity()] + [FriendAccessAllowed] + internal partial class UnsafeNativeMethods + { + /// + /// Critical: This elevates to unmanaged code permission + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, CharSet=CharSet.Unicode, SetLastError=true, EntryPoint="GetTempFileName")] + internal static extern uint _GetTempFileName(string tmpPath, string prefix, uint uniqueIdOrZero, StringBuilder tmpFileName); + + /// + /// Critical: This elevates to unmanaged code permission + /// + [SecurityCritical] + internal static uint GetTempFileName(string tmpPath, string prefix, uint uniqueIdOrZero, StringBuilder tmpFileName) + { + uint result = _GetTempFileName(tmpPath, prefix, uniqueIdOrZero, tmpFileName); + if (result == 0) + { + throw new Win32Exception(); + } + + return result; + } + + /// + /// Critical: This elevates to unmanaged code permission + /// + [SecurityCritical,SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Shell32, CharSet = System.Runtime.InteropServices.CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern int ExtractIconEx( + string szExeFileName, + int nIconIndex, + out NativeMethods.IconHandle phiconLarge, + out NativeMethods.IconHandle phiconSmall, + int nIcons); + + /// + /// Critical: This elevates to unmanaged code permission + /// + [SecurityCritical,SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError=true)] + internal static extern NativeMethods.IconHandle CreateIcon(IntPtr hInstance, int nWidth, int nHeight, byte cPlanes, byte cBitsPixel, byte[] lpbANDbits, byte[] lpbXORbits); + + /// + /// Critical: This elevates to unmanaged code permission + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true)] + public static extern bool CreateCaret(HandleRef hwnd, NativeMethods.BitmapHandle hbitmap, int width, int height); + + /// + /// Critical: This elevates to unmanaged code permission + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true)] + public static extern bool ShowCaret(HandleRef hwnd); + + /// + /// Critical: This elevates to unmanaged code permission + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true)] + public static extern bool HideCaret(HandleRef hwnd); + + /// + /// Critical: This elevates to unmanaged code permission + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] + public static extern bool ShowWindowAsync(HandleRef hWnd, int nCmdShow); + + [DllImport(ExternDll.User32, EntryPoint="LoadImage", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern NativeMethods.IconHandle LoadImageIcon(IntPtr hinst, string stName, int nType, int cxDesired, int cyDesired, int nFlags); + + [DllImport(ExternDll.User32, EntryPoint="LoadImage", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern NativeMethods.CursorHandle LoadImageCursor(IntPtr hinst, string stName, int nType, int cxDesired, int cyDesired, int nFlags); + // uncomment this if you plan to use LoadImage to load anything other than Icons/Cursors. + /* + [DllImport(ExternDll.User32, CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern SafeHandle LoadImage( + IntPtr hinst, string stName, int nType, int cxDesired, int cyDesired, int nFlags); + */ + /* + [DllImport(ExternDll.User32, CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern NativeMethods.IconHandle LoadImage( + IntPtr hinst, string stName, int nType, int cxDesired, int cyDesired, int nFlags); + */ + + /// + /// Critical - performs an elevation. + /// + /// Could be a candidate for safe - as the only information disclosed is whether + /// a certain security measure is on or off. + /// Likely this determination could be made by trying certain actions and failing. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity ] + [DllImport( ExternDll.Urlmon, ExactSpelling=true)] + internal static extern int CoInternetIsFeatureEnabled( int featureEntry , int dwFlags ); + + /// + /// Critical - performs an elevation. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity ] + [DllImport( ExternDll.Urlmon, ExactSpelling=true)] + internal static extern int CoInternetSetFeatureEnabled( int featureEntry , int dwFlags, bool fEnable ); + + /// + /// Critical - performs an elevation. + /// + /// Could be a candidate for safe - as the only information disclosed is whether + /// a certain security measure is on or off. + /// Likely this determination could be made by trying certain actions and failing. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity ] + [DllImport( ExternDll.Urlmon, ExactSpelling=true)] + internal static extern int CoInternetIsFeatureZoneElevationEnabled( + [MarshalAs(UnmanagedType.LPWStr)] string szFromURL, + [MarshalAs(UnmanagedType.LPWStr)] string szToURL, + UnsafeNativeMethods.IInternetSecurityManager secMgr, + int dwFlags + ); + + + /// + /// Critical - call is SUC'ed + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.PresentationHostDll, EntryPoint = "ProcessUnhandledException")] + internal static extern void ProcessUnhandledException_DLL([MarshalAs(UnmanagedType.BStr)] string errMsg); + + /// + /// Critical - performs an elevation. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity ] + [DllImport(ExternDll.Kernel32, CharSet=CharSet.Unicode)] + internal static extern bool GetVersionEx([In, Out] NativeMethods.OSVERSIONINFOEX ver); + /// + /// Critical - performs an elevation. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity ] + [DllImport( ExternDll.Urlmon, ExactSpelling=true)] + internal static extern int CoInternetCreateSecurityManager( + [MarshalAs(UnmanagedType.Interface)] object pIServiceProvider, + [MarshalAs(UnmanagedType.Interface)] out object ppISecurityManager , + int dwReserved ) ; + + + + + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport, ComVisible(false), Guid("79eac9ee-baf9-11ce-8c82-00aa004ba90b"), System.Runtime.InteropServices.InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IInternetSecurityManager + { + void SetSecuritySite( NativeMethods.IInternetSecurityMgrSite pSite); + + unsafe void GetSecuritySite( /* [out] */ void **ppSite); + + /// + /// Critical - performs an elevation. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + void MapUrlToZone( + [In, MarshalAs(UnmanagedType.BStr)] + string pwszUrl, + [Out] out int pdwZone, + [In] int dwFlags); + + unsafe void GetSecurityId( /* [in] */ string pwszUrl, + /* [size_is][out] */ byte *pbSecurityId, + /* [out][in] */ int *pcbSecurityId, + /* [in] */ int dwReserved); + + unsafe void ProcessUrlAction( + /* [in] */ string pwszUrl, + /* [in] */ int dwAction, + /* [size_is][out] */ byte *pPolicy, + /* [in] */ int cbPolicy, + /* [in] */ byte *pContext, + /* [in] */ int cbContext, + /* [in] */ int dwFlags, + /* [in] */ int dwReserved); + + unsafe void QueryCustomPolicy( + /* [in] */ string pwszUrl, + /* [in] */ /*REFGUID*/ void *guidKey, + /* [size_is][size_is][out] */ byte **ppPolicy, + /* [out] */ int *pcbPolicy, + /* [in] */ byte *pContext, + /* [in] */ int cbContext, + /* [in] */ int dwReserved); + + unsafe void SetZoneMapping( /* [in] */ int dwZone, /* [in] */ string lpszPattern, /* [in] */ int dwFlags); + + unsafe void GetZoneMappings( /* [in] */ int dwZone, /* [out] */ /*IEnumString*/ void **ppenumString, /* [in] */ int dwFlags); + } + + /// + /// + /// + /// + /// + [DllImport(ExternDll.Kernel32, SetLastError = true), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] + internal static extern IntPtr LocalFree(IntPtr hMem); + +#if BASE_NATIVEMETHODS + /// + /// SecurityCritical: This code returns a critical resource obtained under an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal unsafe static extern SafeFileHandle CreateFile( + string lpFileName, + uint dwDesiredAccess, + uint dwShareMode, + [In] NativeMethods.SECURITY_ATTRIBUTES lpSecurityAttributes, + int dwCreationDisposition, + int dwFlagsAndAttributes, + IntPtr hTemplateFile); +#endif + + +#if BASE_NATIVEMETHODS + /// + /// Critical: This code is critical because it can be used to + /// pass and force arbitrary data into the tree. We should + /// consider yanking it out all the way + /// + + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + internal static extern IntPtr GetMessageExtraInfo(); +#endif + +#if BASE_NATIVEMETHODS + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, EntryPoint="WaitForMultipleObjectsEx", SetLastError = true, CharSet = CharSet.Auto)] + private static extern int IntWaitForMultipleObjectsEx(int nCount, IntPtr[] pHandles, bool bWaitAll, int dwMilliseconds, bool bAlertable); + + public const int WAIT_FAILED = unchecked((int)0xFFFFFFFF); + + /// + /// Critical - calls IntWaitForMultipleObjectsEx (the real PInvoke method) + /// + [SecurityCritical] + internal static int WaitForMultipleObjectsEx(int nCount, IntPtr[] pHandles, bool bWaitAll, int dwMilliseconds, bool bAlertable) + { + int result = IntWaitForMultipleObjectsEx(nCount, pHandles, bWaitAll, dwMilliseconds, bAlertable); + if(result == UnsafeNativeMethods.WAIT_FAILED) + { + throw new Win32Exception(); + } + + return result; + } + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint="MsgWaitForMultipleObjectsEx", SetLastError=true, ExactSpelling = true, CharSet = CharSet.Auto)] + private static extern int IntMsgWaitForMultipleObjectsEx(int nCount, IntPtr[] pHandles, int dwMilliseconds, int dwWakeMask, int dwFlags); + + /// + /// Critical - calls IntMsgWaitForMultipleObjectsEx (the real PInvoke method) + /// + [SecurityCritical] + internal static int MsgWaitForMultipleObjectsEx(int nCount, IntPtr[] pHandles, int dwMilliseconds, int dwWakeMask, int dwFlags) + { + int result = IntMsgWaitForMultipleObjectsEx(nCount, pHandles, dwMilliseconds, dwWakeMask, dwFlags); + if(result == -1) + { + throw new Win32Exception(); + } + + return result; + } +#endif + + /// + /// Critical: This code elevates to unmanaged code permission + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint="RegisterClassEx", CharSet=CharSet.Unicode, SetLastError=true, BestFitMapping=false)] + internal static extern UInt16 IntRegisterClassEx(NativeMethods.WNDCLASSEX_D wc_d); + + /// + /// Critical - calls IntRegisterClassEx (the real PInvoke method) + /// + [SecurityCritical] + internal static UInt16 RegisterClassEx(NativeMethods.WNDCLASSEX_D wc_d) + { + UInt16 result = IntRegisterClassEx(wc_d); + if(result == 0) + { + throw new Win32Exception(); + } + + return result; + } + + /// + /// Critical: This code elevates to unmanaged code permission + /// + [SecurityCritical,SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint="UnregisterClass",CharSet = CharSet.Auto, SetLastError = true, BestFitMapping=false)] + internal static extern int IntUnregisterClass(IntPtr atomString /*lpClassName*/ , IntPtr hInstance); + + /// + /// Critical - calls IntUnregisterClass (the real PInvoke method) + /// + [SecurityCritical] + internal static void UnregisterClass(IntPtr atomString /*lpClassName*/ , IntPtr hInstance) + { + int result = IntUnregisterClass(atomString, hInstance); + if (result == 0) + { + throw new Win32Exception(); + } + } + +#if !DRT + + /// + /// Critical - performs an elevation. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport("user32.dll", EntryPoint="ChangeWindowMessageFilter", SetLastError=true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool IntChangeWindowMessageFilter(WindowMessage message, MSGFLT dwFlag); + + /// + /// Critical - performs an elevation. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport("user32.dll", EntryPoint = "ChangeWindowMessageFilterEx", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool IntChangeWindowMessageFilterEx(IntPtr hwnd, WindowMessage message, MSGFLT action, [In, Out, Optional] ref CHANGEFILTERSTRUCT pChangeFilterStruct); + + // Note that processes at or below SECURITY_MANDATORY_LOW_RID are not allowed to change the message filter. + // If those processes call this function, it will fail and generate the extended error code, ERROR_ACCESS_DENIED. + /// + /// Critical - calls SecurityCritical methods IntChangeWindowMessageFilter and IntChangeWindowMessageFilterEx. + /// + [SecurityCritical] + internal static MS.Internal.Interop.HRESULT ChangeWindowMessageFilterEx(IntPtr hwnd, WindowMessage message, MSGFLT action, out MSGFLTINFO extStatus) + { + extStatus = MSGFLTINFO.NONE; + + // This API were added for Vista. The Ex version was added for Windows 7. + // If we're not on either, then this message filter isolation doesn't exist. + if (!Utilities.IsOSVistaOrNewer) + { + return MS.Internal.Interop.HRESULT.S_FALSE; + } + + // If we're on Vista rather than Win7 then we can't use the Ex version of this function. + // The Ex version is preferred if possible because this results in process-wide modifications of the filter + // and is deprecated as of Win7. + if (!Utilities.IsOSWindows7OrNewer) + { + // Note that the Win7 MSGFLT_ALLOW/DISALLOW enum values map to the Vista MSGFLT_ADD/REMOVE + if (!IntChangeWindowMessageFilter(message, action)) + { + return (MS.Internal.Interop.HRESULT)Win32Error.GetLastError(); + } + return MS.Internal.Interop.HRESULT.S_OK; + } + + var filterstruct = new CHANGEFILTERSTRUCT { cbSize = (uint)Marshal.SizeOf(typeof(CHANGEFILTERSTRUCT)) }; + if (!IntChangeWindowMessageFilterEx(hwnd, message, action, ref filterstruct)) + { + return (MS.Internal.Interop.HRESULT)Win32Error.GetLastError(); + } + + extStatus = filterstruct.ExtStatus; + return MS.Internal.Interop.HRESULT.S_OK; + } + + /// + /// Critical - performs an elevation. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Urlmon, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)] + private static extern MS.Internal.Interop.HRESULT ObtainUserAgentString(int dwOption, StringBuilder userAgent, ref int length); + + /// + /// Critical - performs an elevation. + /// + [SecurityCritical] + internal static string ObtainUserAgentString() + { + int length = MS.Win32.NativeMethods.MAX_PATH; + StringBuilder userAgentBuffer = new StringBuilder(length); + MS.Internal.Interop.HRESULT hr = ObtainUserAgentString(0 /*reserved. must be 0*/, userAgentBuffer, ref length); + + // Dev10 821573 - Installing .NET 4.0 adds two parts to the user agent string, i.e. + // .NET4.0C and .NET4.0E, potentially causing the user agent string to overflow its + // documented maximum length of MAX_PATH. Turns out ObtainUserAgentString can return + // a longer string if asked to do so. Therefore we grow the string dynamically when + // needed, accommodating for this failure condition. + if (hr == MS.Internal.Interop.HRESULT.E_OUTOFMEMORY) + { + userAgentBuffer = new StringBuilder(length); + hr = ObtainUserAgentString(0 /*reserved. must be 0*/, userAgentBuffer, ref length); + } + + hr.ThrowIfFailed(); + + return userAgentBuffer.ToString(); + } + + // note that this method exists in UnsafeNativeMethodsCLR.cs but with a different signature + // using a HandleRef for the hWnd instead of an IntPtr, and not using an IntPtr for lParam + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + internal static extern IntPtr SendMessage(IntPtr hWnd, WindowMessage msg, IntPtr wParam, IntPtr lParam); + + + // note that this method exists in UnsafeNativeMethodsCLR.cs but with a different signature + // using a HandleRef for the hWnd instead of an IntPtr, and not using an IntPtr for lParam + /// + /// Critical: This code has the ability to send a message to the wndproc. It exists purely for + /// the secure close scenario. For any other scenario please use the SendMessage call + /// + [DllImport(ExternDll.User32,EntryPoint="SendMessage", CharSet = CharSet.Auto)] + [SecurityCritical,SuppressUnmanagedCodeSecurity] + internal static extern IntPtr UnsafeSendMessage(IntPtr hWnd, WindowMessage msg, IntPtr wParam, IntPtr lParam); + + /// + /// Critical: Registering for system broadcast messages + /// + [DllImport(ExternDll.User32,EntryPoint="RegisterPowerSettingNotification")] + [SecurityCritical,SuppressUnmanagedCodeSecurity] + unsafe internal static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, Guid *pGuid, int Flags); + + /// + /// Critical: Unregistering for system broadcast messages + /// + [DllImport(ExternDll.User32,EntryPoint="UnregisterPowerSettingNotification")] + [SecurityCritical,SuppressUnmanagedCodeSecurity] + unsafe internal static extern IntPtr UnregisterPowerSettingNotification(IntPtr hPowerNotify); + +/* + // + // SendMessage taking a SafeHandle for wParam. Needed by some Win32 messages. e.g. WM_PRINT + // + [DllImport(ExternDll.User32, CharSet = CharSet.Auto)] + internal static extern IntPtr SendMessage(HandleRef hWnd, WindowMessage msg, SafeHandle wParam, IntPtr lParam); +*/ + + // private DllImport - that takes an IconHandle. + /// + /// Critical: This code causes elevation to unmanaged code + /// + [SecurityCritical,SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)] + internal static extern IntPtr SendMessage( HandleRef hWnd, WindowMessage msg, IntPtr wParam, NativeMethods.IconHandle iconHandle ); +#endif + + /// + /// Critical: This code causes elevation to unmanaged code + /// + [SecurityCritical,SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Auto)] + internal static extern void SetLastError(int dwErrorCode); + +#if BASE_NATIVEMETHODS || CORE_NATIVEMETHODS || FRAMEWORK_NATIVEMETHODS + /// + /// Win32 GetLayeredWindowAttributes. + /// + /// + /// + /// + /// + /// + /// + /// Critical: This code calls into unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("user32.dll")] + public static extern bool GetLayeredWindowAttributes( + HandleRef hwnd, IntPtr pcrKey, IntPtr pbAlpha, IntPtr pdwFlags); + internal sealed class SafeFileMappingHandle : SafeHandleZeroOrMinusOneIsInvalid + { + /// + /// Critical: base class enforces link demand and inheritance demand + /// + [SecurityCritical] + internal SafeFileMappingHandle(IntPtr handle) : base(false) + { + SetHandle(handle); + } + + /// + /// Critical: base class enforces link demand and inheritance demand + /// TreatAsSafe: Creating this is ok, accessing the pointer is bad + /// + [SecurityCritical,SecurityTreatAsSafe] + internal SafeFileMappingHandle() : base(true) + { + } + + /// + /// Critical: base class enforces link demand and inheritance demand + /// TreatAsSafe: This call is safe + /// + public override bool IsInvalid + { + [SecurityCritical,SecurityTreatAsSafe] + get + { + return handle == IntPtr.Zero; + } + } + + /// + /// Critical - as this function does an elevation to close a handle. + /// TreatAsSafe - as this can at best be used to destabilize one's own app. + /// + [SecurityCritical, SecurityTreatAsSafe] + protected override bool ReleaseHandle() + { + new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); + try + { + return CloseHandleNoThrow(new HandleRef(null, handle)); + } + finally + { + SecurityPermission.RevertAssert(); + } + } + } + internal sealed class SafeViewOfFileHandle : SafeHandleZeroOrMinusOneIsInvalid + { + /// + /// Critical: This code calls into a base class which link demands for unmanaged code + /// TreatAsSafe:Creating this is ok it is acessing the pointers in it that can be risky + /// + [SecurityCritical,SecurityTreatAsSafe] + internal SafeViewOfFileHandle() : base(true) { } + + /// + /// Critical: This code accesses an unsafe object (pointer) and returns it as a pointer + /// + internal unsafe void* Memory + { + [SecurityCritical] + get + { + Debug.Assert(handle != IntPtr.Zero); + return (void*)handle; + } + } + + /// + /// Critical - as this function does an elevation to close a handle. + /// TreatAsSafe - as this can at best be used to destabilize one's own app. + /// + [SecurityCritical, SecurityTreatAsSafe] + override protected bool ReleaseHandle() + { + new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); + try + { + return UnsafeNativeMethods.UnmapViewOfFileNoThrow(new HandleRef(null, handle)); + } + finally + { + SecurityPermission.RevertAssert(); + } + } + } + + /// + /// SecurityCritical: This code returns critical resource obtained under an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal unsafe static extern SafeFileMappingHandle CreateFileMapping(SafeFileHandle hFile, NativeMethods.SECURITY_ATTRIBUTES lpFileMappingAttributes, int flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName); + + /// + /// SecurityCritical: This code returns a critical resource obtained under an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, SetLastError = true)] + internal static extern SafeViewOfFileHandle MapViewOfFileEx(SafeFileMappingHandle hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, IntPtr dwNumberOfBytesToMap, IntPtr lpBaseAddress); +#endif // BASE_NATIVEMETHODS + + + /// + /// Critical: LinkDemand on Marshal.GetLastWin32Error + /// TreatAsSafe: Getting an error code isn't unsafe + /// Note: If a SupressUnmanagedCodeSecurity attribute is ever added to IntsetWindowLong(Ptr), we'd need to be Critical + /// + [SecurityCritical, SecurityTreatAsSafe] + internal static IntPtr SetWindowLong(HandleRef hWnd, int nIndex, IntPtr dwNewLong) + { + IntPtr result = IntPtr.Zero; + + if (IntPtr.Size == 4) + { + // use SetWindowLong + Int32 tempResult = NativeMethodsSetLastError.SetWindowLong(hWnd, nIndex, NativeMethods.IntPtrToInt32(dwNewLong)); + result = new IntPtr(tempResult); + } + else + { + // use SetWindowLongPtr + result = NativeMethodsSetLastError.SetWindowLongPtr(hWnd, nIndex, dwNewLong); + } + + return result; + } + + /// + /// Critical - it calls IntCriticalSetWindowLongPtr() / IntCriticalSetWindowLong(), which are Critical + /// + [SecurityCritical] + internal static IntPtr CriticalSetWindowLong(HandleRef hWnd, int nIndex, IntPtr dwNewLong) + { + IntPtr result = IntPtr.Zero; + + if (IntPtr.Size == 4) + { + // use SetWindowLong + Int32 tempResult = NativeMethodsSetLastError.SetWindowLong(hWnd, nIndex, NativeMethods.IntPtrToInt32(dwNewLong)); + result = new IntPtr(tempResult); + } + else + { + // use SetWindowLongPtr + result = NativeMethodsSetLastError.SetWindowLongPtr(hWnd, nIndex, dwNewLong); + } + + return result; + } + + /// + /// Critical - This calls SetLatError() and IntCriticalSetWindowLongPtr() / IntCriticalSetWindowLong(), which are Critical + /// + [SecurityCritical] + internal static IntPtr CriticalSetWindowLong(HandleRef hWnd, int nIndex, NativeMethods.WndProc dwNewLong) + { + int errorCode; + IntPtr retVal; + + if (IntPtr.Size == 4) + { + Int32 tempRetVal = NativeMethodsSetLastError.SetWindowLongWndProc(hWnd, nIndex, dwNewLong); + errorCode = Marshal.GetLastWin32Error(); + retVal = new IntPtr(tempRetVal); + } + else + { + retVal = NativeMethodsSetLastError.SetWindowLongPtrWndProc(hWnd, nIndex, dwNewLong); + errorCode = Marshal.GetLastWin32Error(); + } + + if (retVal == IntPtr.Zero) + { + if (errorCode != 0) + { + throw new System.ComponentModel.Win32Exception(errorCode); + } + } + + return retVal; + } + + /// + /// SecurityCritical: This code happens to return a critical resource and causes unmanaged code elevation + /// + [SecurityCritical] + internal static IntPtr GetWindowLongPtr(HandleRef hWnd, int nIndex ) + { + IntPtr result = IntPtr.Zero; + int error = 0; + + if (IntPtr.Size == 4) + { + // use getWindowLong + Int32 tempResult = NativeMethodsSetLastError.GetWindowLong(hWnd, nIndex); + error = Marshal.GetLastWin32Error(); + result = new IntPtr(tempResult); + } + else + { + // use GetWindowLongPtr + result = NativeMethodsSetLastError.GetWindowLongPtr(hWnd, nIndex); + error = Marshal.GetLastWin32Error(); + } + + if ((result == IntPtr.Zero) && (error != 0)) + { + // To be consistent with out other PInvoke wrappers + // we should "throw" here. But we don't want to + // introduce new "throws" w/o time to follow up on any + // new problems that causes. + Debug.WriteLine("GetWindowLongPtr failed. Error = " + error); + // throw new System.ComponentModel.Win32Exception(error); + } + + return result; + } + + /// + /// SecurityCritical: This code happens to return a critical resource and causes unmanaged code elevation + /// + [SecurityCritical] + internal static Int32 GetWindowLong(HandleRef hWnd, int nIndex ) + { + int iResult = 0; + IntPtr result = IntPtr.Zero; + int error = 0; + + if (IntPtr.Size == 4) + { + // use GetWindowLong + iResult = NativeMethodsSetLastError.GetWindowLong(hWnd, nIndex); + error = Marshal.GetLastWin32Error(); + result = new IntPtr(iResult); + } + else + { + // use GetWindowLongPtr + result = NativeMethodsSetLastError.GetWindowLongPtr(hWnd, nIndex); + error = Marshal.GetLastWin32Error(); + iResult = NativeMethods.IntPtrToInt32(result); + } + + if ((result == IntPtr.Zero) && (error != 0)) + { + // To be consistent with out other PInvoke wrappers + // we should "throw" here. But we don't want to + // introduce new "throws" w/o time to follow up on any + // new problems that causes. + Debug.WriteLine("GetWindowLong failed. Error = " + error); + // throw new System.ComponentModel.Win32Exception(error); + } + + return iResult; + } + + /// + /// Critical: Call critical method IntGetWindowLongWndProc and IntGetWindowLongWndProcPtr that causes unmanaged code elevation. + /// LinkDemand on Win32Exception constructor but throwing an exception isn't unsafe + /// + [SecurityCritical] + internal static NativeMethods.WndProc GetWindowLongWndProc(HandleRef hWnd) + { + NativeMethods.WndProc returnValue = null; + int error = 0; + + if (IntPtr.Size == 4) + { + // use getWindowLong + returnValue = NativeMethodsSetLastError.GetWindowLongWndProc(hWnd, NativeMethods.GWL_WNDPROC); + error = Marshal.GetLastWin32Error(); + } + else + { + // use GetWindowLongPtr + returnValue = NativeMethodsSetLastError.GetWindowLongPtrWndProc(hWnd, NativeMethods.GWL_WNDPROC); + error = Marshal.GetLastWin32Error(); + } + + if (null == returnValue) + { + throw new Win32Exception(error); + } + + return returnValue; + } + + /// + /// Critical - Unmanaged code permission is supressed. + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport("winmm.dll", CharSet = CharSet.Unicode)] + internal static extern bool PlaySound([In]string soundName, IntPtr hmod, SafeNativeMethods.PlaySoundFlags soundFlags); + + internal const uint + INTERNET_COOKIE_THIRD_PARTY = 0x10, + INTERNET_COOKIE_EVALUATE_P3P = 0x40, + INTERNET_COOKIE_IS_RESTRICTED = 0x200, + COOKIE_STATE_REJECT = 5; + + //!!! CAUTION + // PresentationHost intercepts calls to InternetGetCookieEx & InternetSetCookieEx and delegates them + // to the browser. It doesn't do this for InternetGetCookie & InternetSetCookie. + // See also Application.Get/SetCookie(). + //!!! + + /// + /// SecurityCritical - calls unmanaged code. + /// + [DllImport(ExternDll.Wininet, SetLastError=true, ExactSpelling=true, EntryPoint="InternetGetCookieExW", CharSet=CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity, SecurityCritical] + internal static extern bool InternetGetCookieEx([In]string Url, [In]string cookieName, + [Out] StringBuilder cookieData, [In, Out] ref UInt32 pchCookieData, uint flags, IntPtr reserved); + + /// + /// SecurityCritical - calls unmanaged code. + /// + [DllImport(ExternDll.Wininet, SetLastError = true, ExactSpelling = true, EntryPoint = "InternetSetCookieExW", CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + [SecurityCritical] + internal static extern uint InternetSetCookieEx([In]string Url, [In]string CookieName, [In]string cookieData, uint flags, [In] string p3pHeader); + +#if DRT_NATIVEMETHODS + + [DllImport(ExternDll.User32, ExactSpelling = true, EntryPoint = "mouse_event", CharSet = CharSet.Auto)] + internal static extern void Mouse_event(int flags, int dx, int dy, int dwData, IntPtr extrainfo); + +#endif + ///////////////////////////// + // needed by Framework + + /// + /// Critical - calls unmanaged code + /// + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + [SecurityCritical] + internal static extern int GetLocaleInfoW(int locale, int type, string data, int dataSize); + + /// + /// Critical - calls unmanaged code + /// + [DllImport(ExternDll.Kernel32, ExactSpelling = true, SetLastError = true)] + [SuppressUnmanagedCodeSecurity] + [SecurityCritical] + internal static extern int FindNLSString(int locale, uint flags, [MarshalAs(UnmanagedType.LPWStr)]string sourceString, int sourceCount, [MarshalAs(UnmanagedType.LPWStr)]string findString, int findCount, out int found); + + + //[DllImport(ExternDll.Psapi, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)] + //public static extern int GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, StringBuilder buffer, int length); + + // + // OpenProcess + // + public const int PROCESS_VM_READ = 0x0010; + public const int PROCESS_QUERY_INFORMATION = 0x0400; + + //[DllImport(ExternDll.Kernel32, SetLastError = true, CharSet = CharSet.Auto)] + //public static extern IntPtr OpenProcess(int dwDesiredAccess, bool fInherit, int dwProcessId); + + [DllImport(ExternDll.User32, EntryPoint = "SetWindowText", CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false)] + private static extern bool IntSetWindowText(HandleRef hWnd, string text); + + /// + /// Critical: LinkDemand on Win32Exception constructor + /// TreatAsSafe: Throwing an exception isn't unsafe + /// Note: If a SupressUnmanagedCodeSecurity attribute is ever added to IntSetWindowText, we'd need to be Critical + /// + [SecurityCritical, SecurityTreatAsSafe] + internal static void SetWindowText(HandleRef hWnd, string text) + { + if (IntSetWindowText(hWnd, text) == false) + { + throw new Win32Exception(); + } + } + /// + /// Critical: This code calls into unmanaged code + /// + [SecurityCritical,SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint = "GetIconInfo", CharSet = CharSet.Auto, SetLastError = true)] + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] + private static extern bool GetIconInfoImpl(HandleRef hIcon, [Out] ICONINFO_IMPL piconinfo); + + [StructLayout(LayoutKind.Sequential)] + internal class ICONINFO_IMPL + { + public bool fIcon = false; + public int xHotspot = 0; + public int yHotspot = 0; + public IntPtr hbmMask = IntPtr.Zero; + public IntPtr hbmColor = IntPtr.Zero; + } + + // FOR REVIEW + // note that a different-signature version of this method is defined in SafeNativeMethodsCLR.cs, but + // this appears to be an intentional override of the functionality. Seems odd if the real method + // is really safe to reimplement it in an unsafe manner. Need to review this. + /// + /// Critical: This code calls into unmanaged code GetIconInfoImpl + /// + [SecurityCritical] + internal static void GetIconInfo(HandleRef hIcon, out NativeMethods.ICONINFO piconinfo) + { + bool success = false; + int error = 0; + piconinfo = new NativeMethods.ICONINFO(); + ICONINFO_IMPL iconInfoImpl = new ICONINFO_IMPL(); + + SRCS.RuntimeHelpers.PrepareConstrainedRegions(); // Mark the following as special + try + { + // Intentionally empty + } + finally + { + // This block won't be interrupted by certain runtime induced failures or thread abort + success = GetIconInfoImpl(hIcon, iconInfoImpl); + error = Marshal.GetLastWin32Error(); + + if (success) + { + piconinfo.hbmMask = NativeMethods.BitmapHandle.CreateFromHandle(iconInfoImpl.hbmMask); + piconinfo.hbmColor = NativeMethods.BitmapHandle.CreateFromHandle(iconInfoImpl.hbmColor); + piconinfo.fIcon = iconInfoImpl.fIcon; + piconinfo.xHotspot = iconInfoImpl.xHotspot; + piconinfo.yHotspot = iconInfoImpl.yHotspot; + } + } + + if(!success) + { + Debug.WriteLine("GetIconInfo failed. Error = " + error); + + throw new Win32Exception(); + } + } + +#if never + + [DllImport(ExternDll.User32, +#if WIN64 + EntryPoint="GetClassLongPtr", +#endif + CharSet = CharSet.Auto, SetLastError = true) + ] + internal static extern UInt32 GetClassLong(IntPtr hwnd, int nIndex); +#endif + + [DllImport(ExternDll.User32, EntryPoint = "GetWindowPlacement", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + private static extern bool IntGetWindowPlacement(HandleRef hWnd, ref NativeMethods.WINDOWPLACEMENT placement); + + // note: this method exists in UnsafeNativeMethodsCLR.cs, but that method does not have the if/throw implemntation + /// + /// Critical: LinkDemand on Win32Exception constructor + /// TreatAsSafe: Throwing an exception isn't unsafe + /// Note: If a SupressUnmanagedCodeSecurity attribute is ever added to IntGetWindowPlacement, we'd need to be Critical + /// + [SecurityCritical, SecurityTreatAsSafe] + internal static void GetWindowPlacement(HandleRef hWnd, ref NativeMethods.WINDOWPLACEMENT placement) + { + if (IntGetWindowPlacement(hWnd, ref placement) == false) + { + throw new Win32Exception(); + } + } + + + [DllImport(ExternDll.User32, EntryPoint = "SetWindowPlacement", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + private static extern bool IntSetWindowPlacement(HandleRef hWnd, [In] ref NativeMethods.WINDOWPLACEMENT placement); + + // note: this method appears in UnsafeNativeMethodsCLR.cs but does not have the if/throw block + /// + /// Critical: LinkDemand on Win32Exception constructor + /// Note: If a SupressUnmanagedCodeSecurity attribute is ever added to IntSetWindowPlacement, we'd need to be Critical + /// TreatAsSafe: Throwing an exception isn't unsafe + /// + [SecurityCritical, SecurityTreatAsSafe] + internal static void SetWindowPlacement(HandleRef hWnd, [In] ref NativeMethods.WINDOWPLACEMENT placement) + { + if (IntSetWindowPlacement(hWnd, ref placement) == false) + { + throw new Win32Exception(); + } + } + + //[DllImport("secur32.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] + //internal static extern bool GetUserNameExW( + // [In] EXTENDED_NAME_FORMAT nameFormat, + // [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpNameBuffer, + // [In, Out] ref ulong nSize); + + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, CharSet = CharSet.Auto, BestFitMapping = false)] + internal static extern bool SystemParametersInfo(int nAction, int nParam, [In, Out] NativeMethods.ANIMATIONINFO anim, int nUpdate); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern bool SystemParametersInfo(int nAction, int nParam, [In, Out] NativeMethods.ICONMETRICS metrics, int nUpdate); + + + //--------------------------------------------------------------------------- + // SetWindowThemeAttribute() + // - set attributes to control how themes are applied to + // windows. + // + // hwnd - the handle of the window (cannot be NULL) + // + // eAttribute - one of the following: + // + // WTA_NONCLIENT: + // pvAttribute must be a WINDOWTHEMEATTRIBUTE pointer with a valid WTNCA flag + // the default is all flags set to 0 + // + // pvAttribute - pointer to data relevant to property being set size + // is cbAttribute see each property for details. + // + // cbAttribute - size in bytes of the data pointed to by pvAttribute + // + //--------------------------------------------------------------------------- +#if WCP_SYSTEM_THEMES_ENABLED + [DllImport(ExternDll.Uxtheme, CharSet = CharSet.Unicode)] + public static extern uint SetWindowThemeAttribute(HandleRef hwnd, NativeMethods.WINDOWTHEMEATTRIBUTETYPE eAttribute, [In, MarshalAs(UnmanagedType.LPStruct)] NativeMethods.WTA_OPTIONS pvAttribute, int cbAttribute); + public static uint SetWindowThemeAttribute(HandleRef hwnd, NativeMethods.WINDOWTHEMEATTRIBUTETYPE eAttribute, NativeMethods.WTA_OPTIONS pvAttribute) + { + return SetWindowThemeAttribute(hwnd, eAttribute, pvAttribute, Marshal.SizeOf(typeof(NativeMethods.WTA_OPTIONS))); + } +#endif + + + //--------------------------------------------------------------------------- + // BeginPanningFeedback - Visual feedback init function related to pan gesture + // + // HWND hwnd - The handle to the Target window that will receive feedback + // + //--------------------------------------------------------------------------- + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Uxtheme, CharSet = CharSet.Unicode)] + public static extern bool BeginPanningFeedback(HandleRef hwnd); + + //--------------------------------------------------------------------------- + // UpdatePanningFeedback : Visual feedback function related to pan gesture + // Can Be called only after a BeginPanningFeedback call + // + // HWND hwnd - The handle to the Target window that will receive feedback + // For the method to succeed this must be the same hwnd as provided in + // BeginPanningFeedback + // + // LONG lTotalOverpanOffsetX - The Total displacement that the window has moved in the horizontal direction + // since the end of scrollable region was reached. The API would move the window by the distance specified + // A maximum displacement of 30 pixels is allowed + // + // LONG lTotalOverpanOffsetY - The Total displacement that the window has moved in the horizontal direction + // since the end of scrollable + // region was reached. The API would move the window by the distance specified + // A maximum displacement of 30 pixels is allowed + // + // BOOL fInInertia - Flag dictating whether the Application is handling a WM_GESTURE message with the + // GF_INERTIA FLAG set + // + // Incremental calls to UpdatePanningFeedback should make sure they always pass + // the sum of the increments and not just the increment themselves + // Eg : If the initial displacement is 10 pixels and the next displacement 10 pixels + // the second call would be with the parameter as 20 pixels as opposed to 10 + // Eg : UpdatePanningFeedback(hwnd, 10, 10, TRUE) + // + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Uxtheme, CharSet = CharSet.Unicode)] + public static extern bool UpdatePanningFeedback( + HandleRef hwnd, + int lTotalOverpanOffsetX, + int lTotalOverpanOffsetY, + bool fInInertia); + + //--------------------------------------------------------------------------- + // + // EndPanningFeedback :Visual feedback reset function related to pan gesture + // Terminates any existing animation that was in process or set up by BeginPanningFeedback and UpdatePanningFeedback + // The EndPanningFeedBack needs to be called Prior to calling any BeginPanningFeedBack if we have already + // called a BeginPanningFeedBack followed by one/ more UpdatePanningFeedback calls + // + // HWND hwnd - The handle to the Target window that will receive feedback + // + // BOOL fAnimateBack - Flag to indicate whether you wish the displaced window to move back + // to the original position via animation or a direct jump. + // Either way, the method will try to restore the moved window. + // The latter case exists for compatibility with legacy apps. + // + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Uxtheme, CharSet = CharSet.Unicode)] + public static extern bool EndPanningFeedback( + HandleRef hwnd, + bool fAnimateBack); + + /// + /// + /// + [DllImport(ExternDll.Kernel32, CharSet = CharSet.Auto, SetLastError = true)] + public static extern bool SetEvent(IntPtr hEvent); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern int SetEvent([In] SafeWaitHandle hHandle); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern int WaitForSingleObject([In] SafeWaitHandle hHandle, [In] int dwMilliseconds); + + + //[DllImport(ExternDll.Kernel32, SetLastError = true)] + //internal static extern int GetFileSize(SafeFileHandle hFile, ref int lpFileSizeHigh); + + + ////////////////////////////////////// + // Needed by BASE +#if BASE_NATIVEMETHODS + + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)] + internal static extern int GetMouseMovePointsEx( + uint cbSize, + [In] ref NativeMethods.MOUSEMOVEPOINT pointsIn, + [Out] NativeMethods.MOUSEMOVEPOINT[] pointsBufferOut, + int nBufPoints, + uint resolution + ); + + [StructLayout(LayoutKind.Explicit)] + internal unsafe struct ULARGE_INTEGER + { + [FieldOffset(0)] + internal uint LowPart; + + [FieldOffset(4)] + internal uint HighPart; + + [FieldOffset(0)] + internal ulong QuadPart; + } + + [StructLayout(LayoutKind.Explicit)] + internal unsafe struct LARGE_INTEGER + { + [FieldOffset(0)] + internal int LowPart; + + [FieldOffset(4)] + internal int HighPart; + + [FieldOffset(0)] + internal long QuadPart; + } + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, SetLastError = true)] + internal static extern bool GetFileSizeEx( + SafeFileHandle hFile, + ref LARGE_INTEGER lpFileSize + ); + + + /// Win32 constants + internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); + + /// Win32 constants + internal const int PAGE_NOACCESS = 0x01; + /// Win32 constants + internal const int PAGE_READONLY = 0x02; + /// Win32 constants + internal const int PAGE_READWRITE = 0x04; + /// Win32 constants + internal const int PAGE_WRITECOPY = 0x08; + /// Win32 constants + internal const int PAGE_EXECUTE = 0x10; + /// Win32 constants + internal const int PAGE_EXECUTE_READ = 0x20; + /// Win32 constants + internal const int PAGE_EXECUTE_READWRITE = 0x40; + /// Win32 constants + internal const int PAGE_EXECUTE_WRITECOPY = 0x80; + /// Win32 constants + internal const int PAGE_GUARD = 0x100; + /// Win32 constants + internal const int PAGE_NOCACHE = 0x200; + /// Win32 constants + internal const int PAGE_WRITECOMBINE = 0x400; + /// Win32 constants + internal const int MEM_COMMIT = 0x1000; + /// Win32 constants + internal const int MEM_RESERVE = 0x2000; + /// Win32 constants + internal const int MEM_DECOMMIT = 0x4000; + /// Win32 constants + internal const int MEM_RELEASE = 0x8000; + /// Win32 constants + internal const int MEM_FREE = 0x10000; + /// Win32 constants + internal const int MEM_PRIVATE = 0x20000; + /// Win32 constants + internal const int MEM_MAPPED = 0x40000; + /// Win32 constants + internal const int MEM_RESET = 0x80000; + /// Win32 constants + internal const int MEM_TOP_DOWN = 0x100000; + /// Win32 constants + internal const int MEM_WRITE_WATCH = 0x200000; + /// Win32 constants + internal const int MEM_PHYSICAL = 0x400000; + /// Win32 constants + internal const int MEM_4MB_PAGES = unchecked((int)0x80000000); + /// Win32 constants + internal const int SEC_FILE = 0x800000; + /// Win32 constants + internal const int SEC_IMAGE = 0x1000000; + /// Win32 constants + internal const int SEC_RESERVE = 0x4000000; + /// Win32 constants + internal const int SEC_COMMIT = 0x8000000; + /// Win32 constants + internal const int SEC_NOCACHE = 0x10000000; + /// Win32 constants + internal const int MEM_IMAGE = SEC_IMAGE; + /// Win32 constants + internal const int WRITE_WATCH_FLAG_RESET = 0x01; + + /// Win32 constants + internal const int SECTION_ALL_ACCESS = + STANDARD_RIGHTS_REQUIRED | + SECTION_QUERY | + SECTION_MAP_WRITE | + SECTION_MAP_READ | + SECTION_MAP_EXECUTE | + SECTION_EXTEND_SIZE; + + /// Win32 constants + internal const int STANDARD_RIGHTS_REQUIRED = 0x000F0000; + + /// Win32 constants + internal const int SECTION_QUERY = 0x0001; + /// Win32 constants + internal const int SECTION_MAP_WRITE = 0x0002; + /// Win32 constants + internal const int SECTION_MAP_READ = 0x0004; + /// Win32 constants + internal const int SECTION_MAP_EXECUTE = 0x0008; + /// Win32 constants + internal const int SECTION_EXTEND_SIZE = 0x0010; + + /// Win32 constants + internal const int FILE_MAP_COPY = SECTION_QUERY; + /// Win32 constants + internal const int FILE_MAP_WRITE = SECTION_MAP_WRITE; + /// Win32 constants + internal const int FILE_MAP_READ = SECTION_MAP_READ; + /// Win32 constants + internal const int FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS; + + /// + /// + /// + /// + /// + /// + /// + /// + [DllImport(ExternDll.Advapi32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern bool ConvertStringSecurityDescriptorToSecurityDescriptor( + string stringSecurityDescriptor, // security descriptor string + int stringSDRevision, // revision level + ref IntPtr securityDescriptor, // SD + IntPtr securityDescriptorSize // SD size + ); + + /// Win32 constants + internal const int SDDL_REVISION_1 = 1; + /// Win32 constants + internal const int SDDL_REVISION = SDDL_REVISION_1; + + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern SafeFileMappingHandle OpenFileMapping( + int dwDesiredAccess, + bool bInheritHandle, + string lpName + ); + + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Kernel32, SetLastError = true)] + internal static extern IntPtr VirtualAlloc( + IntPtr lpAddress, + UIntPtr dwSize, + int flAllocationType, + int flProtect + ); + + + // + // RIT WM_MOUSEQUERY structure for DWM WM_MOUSEQUERY (see HwndMouseInputSource.cs) + // + [StructLayout(LayoutKind.Sequential, Pack = 1)] // For DWM WM_MOUSEQUERY + internal unsafe struct MOUSEQUERY + { + internal UInt32 uMsg; + internal IntPtr wParam; + internal IntPtr lParam; + internal Int32 ptX; + internal Int32 ptY; + internal IntPtr hwnd; + } + + /// + /// Critical as this code performs an elevation (via SuppressUnmanagedCodeSecurity) + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.Ole32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern int OleIsCurrentClipboard(IComDataObject pDataObj); + + [DllImport(ExternDll.Kernel32, ExactSpelling = true, CharSet = CharSet.Auto)] + internal static extern int GetOEMCP(); + +#if never + [DllImport("user32.dll", CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)] + internal static extern int ToUnicode(int nVirtKey, int nScanCode, byte[] keystate, StringBuilder text, int cch, int flags); +#endif + + // WinEvent fired when new Avalon UI is created + public const int EventObjectUIFragmentCreate = 0x6FFFFFFF; + + + ////////////////////////////////// + // Needed by FontCache + + [DllImport("ntdll.dll")] + internal static extern int RtlNtStatusToDosError(int Status); + + internal static bool NtSuccess(int err) + { + return err >= STATUS_SUCCESS; + } + + /// + /// Critical: LinkDemand on Win32Exception constructor + /// TreatAsSafe: Throwing an exception isn't unsafe + /// + [SecurityCritical, SecurityTreatAsSafe] + internal static void NtCheck(int err) + { + if (!NtSuccess(err)) + { + int win32error = RtlNtStatusToDosError(err); + throw new System.ComponentModel.Win32Exception(win32error); + } + } + + internal const int STATUS_SUCCESS = 0; + internal const int STATUS_TIMEOUT = 0x00000102; + internal const int STATUS_BUFFER_TOO_SMALL = unchecked((int)0xC0000023); + +#endif // BASE_NATIVEMETHODS + + // + // COM Helper Methods + // + + /// + /// Critical: Satisfies a LinkDemand on releasecom call. + /// + [SecurityCritical] + internal static int SafeReleaseComObject(object o) + { + int refCount = 0; + + // Validate + if (o != null) + { + if (Marshal.IsComObject(o)) + { + refCount = Marshal.ReleaseComObject(o); + } + } + + return refCount; + } + +#if WINDOWS_BASE + /// + /// Critical as this code performs an elevation. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.Wininet, EntryPoint = "GetUrlCacheConfigInfoW", SetLastError=true)] + internal static extern bool GetUrlCacheConfigInfo( + ref NativeMethods.InternetCacheConfigInfo pInternetCacheConfigInfo, + ref UInt32 cbCacheConfigInfo, + UInt32 /* DWORD */ fieldControl + ); +#endif + + /// + /// Critical: takes an hwnd, calls unmanaged code + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport("WtsApi32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool WTSRegisterSessionNotification(IntPtr hwnd, uint dwFlags); + + /// + /// Critical: takes an hwnd, calls unmanaged code + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport("WtsApi32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool WTSUnRegisterSessionNotification(IntPtr hwnd); + + /// + /// Critical: Calls unmanaged code. Returns native process handle. + /// + [SecurityCritical] + [DllImport(ExternDll.Kernel32, SetLastError = true)] + public static extern IntPtr GetCurrentProcess(); + + public const int DUPLICATE_CLOSE_SOURCE = 1; + public const int DUPLICATE_SAME_ACCESS = 2; + + /// + /// Critical: Calls unmanaged code. Returns native process handle. + /// + [SecurityCritical] + [DllImport(ExternDll.Kernel32, SetLastError = true)] + public static extern bool DuplicateHandle( + IntPtr hSourceProcess, + SafeWaitHandle hSourceHandle, + IntPtr hTargetProcessHandle, + out IntPtr hTargetHandle, + uint dwDesiredAccess, + bool fInheritHandle, + uint dwOptions + ); + + // + // + // + + [StructLayout(LayoutKind.Sequential)] + public unsafe struct PROFILEHEADER + { + public uint phSize; // profile size in bytes + public uint phCMMType; // CMM for this profile + public uint phVersion; // profile format version number + public uint phClass; // type of profile + public NativeMethods.ColorSpace phDataColorSpace; // color space of data + public uint phConnectionSpace; // PCS + public uint phDateTime_0; // date profile was created + public uint phDateTime_1; // date profile was created + public uint phDateTime_2; // date profile was created + public uint phSignature; // magic number ("Reserved for internal use.") + public uint phPlatform; // primary platform + public uint phProfileFlags; // various bit settings + public uint phManufacturer; // device manufacturer + public uint phModel; // device model number + public uint phAttributes_0; // device attributes + public uint phAttributes_1; // device attributes + public uint phRenderingIntent; // rendering intent + public uint phIlluminant_0; // profile illuminant + public uint phIlluminant_1; // profile illuminant + public uint phIlluminant_2; // profile illuminant + public uint phCreator; // profile creator + public fixed byte phReserved[44]; + }; + + [StructLayout(LayoutKind.Sequential)] + public unsafe struct PROFILE + { + public NativeMethods.ProfileType dwType; // profile type + + /// + /// Critical: Pointer field. + /// + [SecurityCritical] + public void* pProfileData; // either the filename of the profile or buffer containing profile depending upon dwtype + public uint cbDataSize; // size in bytes of pProfileData + }; + + /// The IsIconic function determines whether the specified window is minimized (iconic). + /// + /// Critical: Calls unmanaged code. + /// + [SecurityCritical,SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool IsIconic(IntPtr hWnd); + + public enum HookType : int + { + WH_JOURNALRECORD = 0, + WH_JOURNALPLAYBACK = 1, + WH_KEYBOARD = 2, + WH_GETMESSAGE = 3, + WH_CALLWNDPROC = 4, + WH_CBT = 5, + WH_SYSMSGFILTER = 6, + WH_MOUSE = 7, + WH_HARDWARE = 8, + WH_DEBUG = 9, + WH_SHELL = 10, + WH_FOREGROUNDIDLE = 11, + WH_CALLWNDPROCRET = 12, + WH_KEYBOARD_LL = 13, + WH_MOUSE_LL = 14, + } + + [StructLayout(LayoutKind.Sequential)] + public struct MOUSEHOOKSTRUCT + { + public NativeMethods.POINT pt; + public IntPtr hwnd; + public uint wHitTestCode; + public IntPtr dwExtraInfo; + } + + public delegate IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam); + + /// + /// Critical: Calls unmanaged code. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + public static HandleRef SetWindowsHookEx(HookType idHook, HookProc lpfn, IntPtr hMod, int dwThreadId) + { + IntPtr result = IntSetWindowsHookEx(idHook, lpfn, hMod, dwThreadId); + if (result == IntPtr.Zero) + { + throw new Win32Exception(); + } + + return new HandleRef(lpfn, result); + } + + /// + /// Critical: Calls unmanaged code. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, EntryPoint = "SetWindowsHookExW", SetLastError = true)] + private static extern IntPtr IntSetWindowsHookEx(HookType idHook, HookProc lpfn, IntPtr hMod, int dwThreadId); + + /// + /// Critical: Calls unmanaged code. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true)] + public static extern bool UnhookWindowsHookEx(HandleRef hhk); + + /// + /// Critical: Calls unmanaged code. + /// + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(ExternDll.User32, SetLastError = true)] + public static extern IntPtr CallNextHookEx(HandleRef hhk, int nCode, IntPtr wParam, IntPtr lParam); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsTextServices.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsTextServices.cs new file mode 100644 index 00000000000..f56779c5912 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsTextServices.cs @@ -0,0 +1,3820 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ + +using System.Threading; +using System.ComponentModel; +using System.Diagnostics; + +// The SecurityHelper class differs between assemblies and could not actually be +// shared, so it is duplicated across namespaces to prevent name collision. +#if WINDOWS_BASE + using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE + using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK + using MS.Internal.PresentationFramework; +#elif DRT + using MS.Internal.Drt; +#else +#error Attempt to use a class (duplicated across multiple namespaces) from an unknown assembly. +#endif +namespace MS.Win32 +{ + + using Accessibility; + using System.Runtime.CompilerServices; + using System.Runtime.ConstrainedExecution; + using System.Runtime.InteropServices; + using System; + using System.Security; + using System.Security.Permissions; + using System.Collections; + using System.IO; + using System.Text; + using Microsoft.Win32.SafeHandles; + + + //[SuppressUnmanagedCodeSecurity()] + internal partial class UnsafeNativeMethods { + + //------------------------------------------------------ + // + // public Methods + // + //------------------------------------------------------ + + #region public Methods + + /// + /// Critical - calls unmanaged code + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport("msctf.dll")] + internal static extern int TF_CreateThreadMgr(out ITfThreadMgr threadManager); + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [DllImport("msctf.dll")] + public static extern int TF_CreateInputProcessorProfiles(out ITfInputProcessorProfiles profiles); + + /// + /// + /// Critical - calls unmanaged code + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + + [DllImport("msctf.dll")] + public static extern int TF_CreateDisplayAttributeMgr(out ITfDisplayAttributeMgr dam); + + /// + /// + /// Critical - calls unmanaged code + /// + [SuppressUnmanagedCodeSecurity, SecurityCritical] + [DllImport("msctf.dll")] + public static extern int TF_CreateCategoryMgr(out ITfCategoryMgr catmgr); + + #endregion public Methods + + //------------------------------------------------------ + // + // Constants + // + //------------------------------------------------------ + + #region Constants + + /// + public const int TF_CLIENTID_NULL = 0; + + /// + public const char TS_CHAR_EMBEDDED = (char)0xfffc; // unicode 2.1 object replacement character + + /// + public const char TS_CHAR_REGION = (char)0x0000; // region boundary + + /// + public const char TS_CHAR_REPLACEMENT = (char)0xfffd; // hidden text placeholder char, Unicode replacement character + + /// + public const int TS_DEFAULT_SELECTION = -1; + + /// + public const int TS_S_ASYNC = 0x00040300; + + /// + public const int TS_E_NOSELECTION = unchecked((int)0x80040205); + + /// + public const int TS_E_NOLAYOUT = unchecked((int)0x80040206); + + /// + public const int TS_E_INVALIDPOINT = unchecked((int)0x80040207); + + /// + public const int TS_E_SYNCHRONOUS = unchecked((int)0x80040208); + + /// + public const int TS_E_READONLY = unchecked((int)0x80040209); + + /// + public const int TS_E_FORMAT = unchecked((int)0x8004020a); + + /// + public const int TF_INVALID_COOKIE = -1; + + /// + public const int TF_DICTATION_ON = 0x00000001; + + /// + public const int TF_COMMANDING_ON = 0x00000008; + + /// + public static readonly Guid IID_ITextStoreACPSink = new Guid(0x22d44c94, 0xa419, 0x4542, 0xa2, 0x72, 0xae, 0x26, 0x09, 0x3e, 0xce, 0xcf); + + /// + public static readonly Guid IID_ITfThreadFocusSink = new Guid(0xc0f1db0c, 0x3a20, 0x405c, 0xa3, 0x03, 0x96, 0xb6, 0x01, 0x0a, 0x88, 0x5f); + + /// + public static readonly Guid IID_ITfTextEditSink = new Guid(0x8127d409, 0xccd3, 0x4683, 0x96, 0x7a, 0xb4, 0x3d, 0x5b, 0x48, 0x2b, 0xf7); + + /// + public static readonly Guid IID_ITfLanguageProfileNotifySink = new Guid(0x43c9fe15, 0xf494, 0x4c17, 0x9d, 0xe2, 0xb8, 0xa4, 0xac, 0x35, 0x0a, 0xa8); + + /// + public static readonly Guid IID_ITfCompartmentEventSink = new Guid(0x743abd5f, 0xf26d, 0x48df, 0x8c, 0xc5, 0x23, 0x84, 0x92, 0x41, 0x9b, 0x64); + + /// + public static readonly Guid IID_ITfTransitoryExtensionSink = new Guid(0xa615096f, 0x1c57, 0x4813, 0x8a, 0x15, 0x55, 0xee, 0x6e, 0x5a, 0x83, 0x9c); + + /// + public static readonly Guid GUID_TFCAT_TIP_KEYBOARD = new Guid(0x34745c63, 0xb2f0, 0x4784, 0x8b, 0x67, 0x5e, 0x12, 0xc8, 0x70, 0x1a, 0x31); +/* + /// + public static readonly Guid GUID_TFCAT_TIP_SPEECH = new Guid("b5a73cd1-8355-426b-a161-259808f26b14"); + + /// + public static readonly Guid GUID_TFCAT_TIP_HANDWRITING = new Guid("246ecb87-c2f2-4abe-905b-c8b38add2c43"); +*/ + + + /// + public static readonly Guid GUID_PROP_ATTRIBUTE = new Guid(0x34b45670, 0x7526, 0x11d2, 0xa1, 0x47, 0x00, 0x10, 0x5a, 0x27, 0x99, 0xb5); + + /// + public static readonly Guid GUID_PROP_LANGID = new Guid(0x3280ce20, 0x8032, 0x11d2, 0xb6, 0x03, 0x00, 0x10, 0x5a, 0x27, 0x99, 0xb5); + + /// + public static readonly Guid GUID_PROP_READING = new Guid(0x5463f7c0, 0x8e31, 0x11d2, 0xbf, 0x46, 0x00, 0x10, 0x5a, 0x27, 0x99, 0xb5); + + + /// + public static readonly Guid GUID_PROP_INPUTSCOPE = new Guid(0x1713dd5a, 0x68e7, 0x4a5b, 0x9a, 0xf6, 0x59, 0x2a, 0x59, 0x5c, 0x77, 0x8d); + + /// + public static readonly Guid GUID_COMPARTMENT_KEYBOARD_DISABLED = new Guid( 0x71a5b253, 0x1951, 0x466b, 0x9f, 0xbc, 0x9c, 0x88, 0x08, 0xfa, 0x84, 0xf2); + + /// + public static Guid GUID_COMPARTMENT_KEYBOARD_OPENCLOSE = new Guid( 0x58273aad, 0x01bb, 0x4164, 0x95, 0xc6, 0x75, 0x5b, 0xa0, 0xb5, 0x16, 0x2d); + + /// + public static readonly Guid GUID_COMPARTMENT_HANDWRITING_OPENCLOSE = new Guid( 0xf9ae2c6b, 0x1866, 0x4361, 0xaf, 0x72, 0x7a, 0xa3, 0x09, 0x48, 0x89, 0x0e); + + /// + public static readonly Guid GUID_COMPARTMENT_SPEECH_DISABLED = new Guid( 0x56c5c607, 0x0703, 0x4e59, 0x8e, 0x52, 0xcb, 0xc8, 0x4e, 0x8b, 0xbe, 0x35); + + /// + public static readonly Guid GUID_COMPARTMENT_SPEECH_OPENCLOSE = new Guid( 0x544d6a63, 0xe2e8, 0x4752, 0xbb, 0xd1, 0x00, 0x09, 0x60, 0xbc, 0xa0, 0x83); + + /// + public static readonly Guid GUID_COMPARTMENT_SPEECH_GLOBALSTATE = new Guid( 0x2a54fe8e, 0x0d08, 0x460c, 0xa7, 0x5d, 0x87, 0x03, 0x5f, 0xf4, 0x36, 0xc5); + + /// + public static readonly Guid GUID_COMPARTMENT_KEYBOARD_INPUTMODE_CONVERSION = new Guid( 0xccf05dd8, 0x4a87, 0x11d7, 0xa6, 0xe2, 0x00, 0x06, 0x5b, 0x84, 0x43, 0x5c); + + /// + public static readonly Guid GUID_COMPARTMENT_KEYBOARD_INPUTMODE_SENTENCE = new Guid( 0xccf05dd9, 0x4a87, 0x11d7, 0xa6, 0xe2, 0x00, 0x06, 0x5b, 0x84, 0x43, 0x5c); + + /// + public static readonly Guid GUID_COMPARTMENT_TRANSITORYEXTENSION = new Guid( 0x8be347f5, 0xc7a0, 0x11d7, 0xb4, 0x08, 0x00, 0x06, 0x5b, 0x84, 0x43, 0x5c); + + /// + public static readonly Guid GUID_COMPARTMENT_TRANSITORYEXTENSION_DOCUMENTMANAGER = new Guid( 0x8be347f7, 0xc7a0, 0x11d7, 0xb4, 0x08, 0x00, 0x06, 0x5b, 0x84, 0x43, 0x5c); + + /// + public static readonly Guid GUID_COMPARTMENT_TRANSITORYEXTENSION_PARENT = new Guid( 0x8be347f8, 0xc7a0, 0x11d7, 0xb4, 0x08, 0x00, 0x06, 0x5b, 0x84, 0x43, 0x5c); + + /// + public static readonly Guid Clsid_SpeechTip = new Guid(0xdcbd6fa8, 0x032f, 0x11d3, 0xb5, 0xb1, 0x00, 0xc0, 0x4f, 0xc3, 0x24, 0xa1); + + /// + public static readonly Guid Guid_Null = new Guid(0,0,0,0,0,0,0,0,0,0,0); + + /// + public static readonly Guid IID_ITfFnCustomSpeechCommand = new Guid(0xfca6c349, 0xa12f, 0x43a3, 0x8d, 0xd6, 0x5a, 0x5a, 0x42, 0x82, 0x57, 0x7b); + + /// + public static readonly Guid IID_ITfFnReconversion = new Guid("4cea93c0-0a58-11d3-8df0-00105a2799b5"); + + /// + public static readonly Guid IID_ITfFnConfigure = new Guid(0x88f567c6, 0x1757, 0x49f8, 0xa1, 0xb2, 0x89, 0x23, 0x4c, 0x1e, 0xef, 0xf9); + + /// + public static readonly Guid IID_ITfFnConfigureRegisterWord = new Guid(0xbb95808a, 0x6d8f, 0x4bca, 0x84, 0x00, 0x53, 0x90, 0xb5, 0x86, 0xae, 0xdf); + +/* + + /// + public static readonly Guid TSATTRID_OTHERS = new Guid(0xb3c32af9,0x57d0,0x46a9,0xbc,0xa8,0xda,0xc2,0x38,0xa1,0x30,0x57); + +*/ + +/* + /// + public static readonly Guid TSATTRID_Font = new Guid(0x573ea825,0x749b,0x4f8a,0x9c,0xfd,0x21,0xc3,0x60,0x5c,0xa8,0x28); +*/ + /// + public static readonly Guid TSATTRID_Font_FaceName = new Guid(0xb536aeb6,0x053b,0x4eb8,0xb6,0x5a,0x50,0xda,0x1e,0x81,0xe7,0x2e); + /// + public static readonly Guid TSATTRID_Font_SizePts = new Guid(0xc8493302,0xa5e9,0x456d,0xaf,0x04,0x80,0x05,0xe4,0x13,0x0f,0x03); +/* + /// + public static readonly Guid TSATTRID_Font_Style = new Guid(0x68b2a77f,0x6b0e,0x4f28,0x81,0x77,0x57,0x1c,0x2f,0x3a,0x42,0xb1); + /// + public static readonly Guid TSATTRID_Font_Style_Bold = new Guid(0x48813a43,0x8a20,0x4940,0x8e,0x58,0x97,0x82,0x3f,0x7b,0x26,0x8a); + /// + public static readonly Guid TSATTRID_Font_Style_Italic = new Guid(0x8740682a,0xa765,0x48e1,0xac,0xfc,0xd2,0x22,0x22,0xb2,0xf8,0x10); + /// + public static readonly Guid TSATTRID_Font_Style_SmallCaps = new Guid(0xfacb6bc6,0x9100,0x4cc6,0xb9,0x69,0x11,0xee,0xa4,0x5a,0x86,0xb4); + /// + public static readonly Guid TSATTRID_Font_Style_Capitalize = new Guid(0x7d85a3ba, 0xb4fd, 0x43b3, 0xbe, 0xfc, 0x6b, 0x98, 0x5c, 0x84, 0x31, 0x41); + /// + public static readonly Guid TSATTRID_Font_Style_Uppercase = new Guid(0x33a300e8, 0xe340, 0x4937, 0xb6, 0x97, 0x8f, 0x23, 0x40, 0x45, 0xcd, 0x9a); + /// + public static readonly Guid TSATTRID_Font_Style_Lowercase = new Guid(0x76d8ccb5, 0xca7b, 0x4498, 0x8e, 0xe9, 0xd5, 0xc4, 0xf6, 0xf7, 0x4c, 0x60); + /// + public static readonly Guid TSATTRID_Font_Style_Animation = new Guid(0xdcf73d22, 0xe029, 0x47b7, 0xbb, 0x36, 0xf2, 0x63, 0xa3, 0xd0, 0x04, 0xcc); + /// + public static readonly Guid TSATTRID_Font_Style_Animation_LasVegasLights = new Guid(0xf40423d5, 0xf87, 0x4f8f, 0xba, 0xda, 0xe6, 0xd6, 0xc, 0x25, 0xe1, 0x52); + /// + public static readonly Guid TSATTRID_Font_Style_Animation_BlinkingBackground = new Guid(0x86e5b104, 0x0104, 0x4b10, 0xb5, 0x85, 0x00, 0xf2, 0x52, 0x75, 0x22, 0xb5); + /// + public static readonly Guid TSATTRID_Font_Style_Animation_SparkleText = new Guid(0x533aad20, 0x962c, 0x4e9f, 0x8c, 0x09, 0xb4, 0x2e, 0xa4, 0x74, 0x97, 0x11); + /// + public static readonly Guid TSATTRID_Font_Style_Animation_MarchingBlackAnts = new Guid(0x7644e067, 0xf186, 0x4902, 0xbf, 0xc6, 0xec, 0x81, 0x5a, 0xa2, 0x0e, 0x9d); + /// + public static readonly Guid TSATTRID_Font_Style_Animation_MarchingRedAnts = new Guid(0x78368dad, 0x50fb, 0x4c6f, 0x84, 0x0b, 0xd4, 0x86, 0xbb, 0x6c, 0xf7, 0x81); + /// + public static readonly Guid TSATTRID_Font_Style_Animation_Shimmer = new Guid(0x2ce31b58, 0x5293, 0x4c36, 0x88, 0x09, 0xbf, 0x8b, 0xb5, 0x1a, 0x27, 0xb3); + /// + public static readonly Guid TSATTRID_Font_Style_Animation_WipeDown = new Guid(0x5872e874, 0x367b, 0x4803, 0xb1, 0x60, 0xc9, 0x0f, 0xf6, 0x25, 0x69, 0xd0); + /// + public static readonly Guid TSATTRID_Font_Style_Animation_WipeRight = new Guid(0xb855cbe3, 0x3d2c, 0x4600, 0xb1, 0xe9, 0xe1, 0xc9, 0xce, 0x02, 0xf8, 0x42); + /// + public static readonly Guid TSATTRID_Font_Style_Emboss = new Guid(0xbd8ed742, 0x349e, 0x4e37, 0x82, 0xfb, 0x43, 0x79, 0x79, 0xcb, 0x53, 0xa7); + /// + public static readonly Guid TSATTRID_Font_Style_Engrave = new Guid(0x9c3371de, 0x8332, 0x4897, 0xbe, 0x5d, 0x89, 0x23, 0x32, 0x23, 0x17, 0x9a); + /// + public static readonly Guid TSATTRID_Font_Style_Hidden = new Guid(0xb1e28770, 0x881c, 0x475f, 0x86, 0x3f, 0x88, 0x7a, 0x64, 0x7b, 0x10, 0x90); + /// + public static readonly Guid TSATTRID_Font_Style_Kerning = new Guid(0xcc26e1b4, 0x2f9a, 0x47c8, 0x8b, 0xff, 0xbf, 0x1e, 0xb7, 0xcc, 0xe0, 0xdd); + /// + public static readonly Guid TSATTRID_Font_Style_Outlined = new Guid(0x10e6db31, 0xdb0d, 0x4ac6, 0xa7, 0xf5, 0x9c, 0x9c, 0xff, 0x6f, 0x2a, 0xb4); + /// + public static readonly Guid TSATTRID_Font_Style_Position = new Guid(0x15cd26ab, 0xf2fb, 0x4062, 0xb5, 0xa6, 0x9a, 0x49, 0xe1, 0xa5, 0xcc, 0x0b); + /// + public static readonly Guid TSATTRID_Font_Style_Protected = new Guid(0x1c557cb2, 0x14cf, 0x4554, 0xa5, 0x74, 0xec, 0xb2, 0xf7, 0xe7, 0xef, 0xd4); + /// + public static readonly Guid TSATTRID_Font_Style_Shadow = new Guid(0x5f686d2f, 0xc6cd, 0x4c56, 0x8a, 0x1a, 0x99, 0x4a, 0x4b, 0x97, 0x66, 0xbe); + /// + public static readonly Guid TSATTRID_Font_Style_Spacing = new Guid(0x98c1200d, 0x8f06, 0x409a, 0x8e, 0x49, 0x6a, 0x55, 0x4b, 0xf7, 0xc1, 0x53); + /// + public static readonly Guid TSATTRID_Font_Style_Weight = new Guid(0x12f3189c, 0x8bb0, 0x461b, 0xb1, 0xfa, 0xea, 0xf9, 0x07, 0x04, 0x7f, 0xe0); +*/ + /// + public static readonly Guid TSATTRID_Font_Style_Height = new Guid(0x7e937477, 0x12e6, 0x458b, 0x92, 0x6a, 0x1f, 0xa4, 0x4e, 0xe8, 0xf3, 0x91); +/* + /// + public static readonly Guid TSATTRID_Font_Style_Underline = new Guid(0xc3c9c9f3,0x7902,0x444b,0x9a,0x7b,0x48,0xe7,0x0f,0x4b,0x50,0xf7); + /// + public static readonly Guid TSATTRID_Font_Style_Underline_Single = new Guid(0x1b6720e5,0x0f73,0x4951,0xa6,0xb3,0x6f,0x19,0xe4,0x3c,0x94,0x61); + /// + public static readonly Guid TSATTRID_Font_Style_Underline_Double = new Guid(0x74d24aa6, 0x1db3, 0x4c69, 0xa1, 0x76, 0x31, 0x12, 0x0e, 0x75, 0x86, 0xd5); + /// + public static readonly Guid TSATTRID_Font_Style_Strikethrough = new Guid(0x0c562193,0x2d08,0x4668,0x96,0x01,0xce,0xd4,0x13,0x09,0xd7,0xaf); + /// + public static readonly Guid TSATTRID_Font_Style_Strikethrough_Single = new Guid(0x75d736b6,0x3c8f,0x4b97,0xab,0x78,0x18,0x77,0xcb,0x99,0x0d,0x31); + /// + public static readonly Guid TSATTRID_Font_Style_Strikethrough_Double = new Guid(0x62489b31, 0xa3e7, 0x4f94, 0xac, 0x43, 0xeb, 0xaf, 0x8f, 0xcc, 0x7a, 0x9f); + /// + public static readonly Guid TSATTRID_Font_Style_Overline = new Guid(0xe3989f4a,0x992b,0x4301,0x8c,0xe1,0xa5,0xb7,0xc6,0xd1,0xf3,0xc8); + /// + public static readonly Guid TSATTRID_Font_Style_Overline_Single = new Guid(0x8440d94c,0x51ce,0x47b2,0x8d,0x4c,0x15,0x75,0x1e,0x5f,0x72,0x1b); + /// + public static readonly Guid TSATTRID_Font_Style_Overline_Double = new Guid(0xdc46063a, 0xe115, 0x46e3, 0xbc, 0xd8, 0xca, 0x67, 0x72, 0xaa, 0x95, 0xb4); + /// + public static readonly Guid TSATTRID_Font_Style_Blink = new Guid(0xbfb2c036, 0x7acf, 0x4532, 0xb7, 0x20, 0xb4, 0x16, 0xdd, 0x77, 0x65, 0xa8); + /// + public static readonly Guid TSATTRID_Font_Style_Subscript = new Guid(0x5774fb84,0x389b,0x43bc,0xa7,0x4b,0x15,0x68,0x34,0x7c,0xf0,0xf4); + /// + public static readonly Guid TSATTRID_Font_Style_Superscript = new Guid(0x2ea4993c,0x563c,0x49aa,0x93,0x72,0x0b,0xef,0x09,0xa9,0x25,0x5b); + /// + public static readonly Guid TSATTRID_Font_Style_Color = new Guid(0x857a7a37,0xb8af,0x4e9a,0x81,0xb4,0xac,0xf7,0x00,0xc8,0x41,0x1b); + /// + public static readonly Guid TSATTRID_Font_Style_BackgroundColor = new Guid(0xb50eaa4e, 0x3091, 0x4468, 0x81, 0xdb, 0xd7, 0x9e, 0xa1, 0x90, 0xc7, 0xc7); + + /// + public static readonly Guid TSATTRID_Text = new Guid(0x7edb8e68, 0x81f9, 0x449d, 0xa1, 0x5a, 0x87, 0xa8, 0x38, 0x8f, 0xaa, 0xc0); +*/ + /// + public static readonly Guid TSATTRID_Text_VerticalWriting = new Guid(0x6bba8195,0x046f,0x4ea9,0xb3,0x11,0x97,0xfd,0x66,0xc4,0x27,0x4b); +/* + /// + public static readonly Guid TSATTRID_Text_RightToLeft = new Guid(0xca666e71,0x1b08,0x453d,0xbf,0xdd,0x28,0xe0,0x8c,0x8a,0xaf,0x7a); +*/ + /// + public static readonly Guid TSATTRID_Text_Orientation = new Guid(0x6bab707f,0x8785,0x4c39,0x8b,0x52,0x96,0xf8,0x78,0x30,0x3f,0xfb); +/* + /// + public static readonly Guid TSATTRID_Text_Language = new Guid(0xd8c04ef1,0x5753,0x4c25,0x88,0x87,0x85,0x44,0x3f,0xe5,0xf8,0x19); +*/ + /// + public static readonly Guid TSATTRID_Text_ReadOnly = new Guid(0x85836617,0xde32,0x4afd,0xa5,0x0f,0xa2,0xdb,0x11,0x0e,0x6e,0x4d); +/* + /// + public static readonly Guid TSATTRID_Text_EmbeddedObject = new Guid(0x7edb8e68, 0x81f9, 0x449d, 0xa1, 0x5a, 0x87, 0xa8, 0x38, 0x8f, 0xaa, 0xc0); + /// + public static readonly Guid TSATTRID_Text_Alignment = new Guid(0x139941e6, 0x1767, 0x456d, 0x93, 0x8e, 0x35, 0xba, 0x56, 0x8b, 0x5c, 0xd4); + /// + public static readonly Guid TSATTRID_Text_Alignment_Left = new Guid(0x16ae95d3, 0x6361, 0x43a2, 0x84, 0x95, 0xd0, 0x0f, 0x39, 0x7f, 0x16, 0x93); + /// + public static readonly Guid TSATTRID_Text_Alignment_Right = new Guid(0xb36f0f98, 0x1b9e, 0x4360, 0x86, 0x16, 0x03, 0xfb, 0x08, 0xa7, 0x84, 0x56); + /// + public static readonly Guid TSATTRID_Text_Alignment_Center = new Guid(0xa4a95c16, 0x53bf, 0x4d55, 0x8b, 0x87, 0x4b, 0xdd, 0x8d, 0x42, 0x75, 0xfc); + /// + public static readonly Guid TSATTRID_Text_Alignment_Justify = new Guid(0xed350740, 0xa0f7, 0x42d3, 0x8e, 0xa8, 0xf8, 0x1b, 0x64, 0x88, 0xfa, 0xf0); + /// + public static readonly Guid TSATTRID_Text_Link = new Guid(0x47cd9051, 0x3722, 0x4cd8, 0xb7, 0xc8, 0x4e, 0x17, 0xca, 0x17, 0x59, 0xf5); + /// + public static readonly Guid TSATTRID_Text_Hyphenation = new Guid(0xdadf4525, 0x618e, 0x49eb, 0xb1, 0xa8, 0x3b, 0x68, 0xbd, 0x76, 0x48, 0xe3); + /// + public static readonly Guid TSATTRID_Text_Para = new Guid(0x5edc5822, 0x99dc, 0x4dd6, 0xae, 0xc3, 0xb6, 0x2b, 0xaa, 0x5b, 0x2e, 0x7c); + /// + public static readonly Guid TSATTRID_Text_Para_FirstLineIndent = new Guid(0x07c97a13, 0x7472, 0x4dd8, 0x90, 0xa9, 0x91, 0xe3, 0xd7, 0xe4, 0xf2, 0x9c); + /// + public static readonly Guid TSATTRID_Text_Para_LeftIndent = new Guid(0xfb2848e9, 0x7471, 0x41c9, 0xb6, 0xb3, 0x8a, 0x14, 0x50, 0xe0, 0x18, 0x97); + /// + public static readonly Guid TSATTRID_Text_Para_RightIndent = new Guid(0x2c7f26f9, 0xa5e2, 0x48da, 0xb9, 0x8a, 0x52, 0x0c, 0xb1, 0x65, 0x13, 0xbf); + /// + public static readonly Guid TSATTRID_Text_Para_SpaceAfter = new Guid(0x7b0a3f55, 0x22dc, 0x425f, 0xa4, 0x11, 0x93, 0xda, 0x1d, 0x8f, 0x9b, 0xaa); + /// + public static readonly Guid TSATTRID_Text_Para_SpaceBefore = new Guid(0x8df98589, 0x194a, 0x4601, 0xb2, 0x51, 0x98, 0x65, 0xa3, 0xe9, 0x06, 0xdd); + /// + public static readonly Guid TSATTRID_Text_Para_LineSpacing = new Guid(0x699b380d, 0x7f8c, 0x46d6, 0xa7, 0x3b, 0xdf, 0xe3, 0xd1, 0x53, 0x8d, 0xf3); + /// + public static readonly Guid TSATTRID_Text_Para_LineSpacing_Single = new Guid(0xed350740, 0xa0f7, 0x42d3, 0x8e, 0xa8, 0xf8, 0x1b, 0x64, 0x88, 0xfa, 0xf0); + /// + public static readonly Guid TSATTRID_Text_Para_LineSpacing_OnePtFive = new Guid(0x0428a021, 0x0397, 0x4b57, 0x9a, 0x17, 0x07, 0x95, 0x99, 0x4c, 0xd3, 0xc5); + /// + public static readonly Guid TSATTRID_Text_Para_LineSpacing_Double = new Guid(0x82fb1805, 0xa6c4, 0x4231, 0xac, 0x12, 0x62, 0x60, 0xaf, 0x2a, 0xba, 0x28); + /// + public static readonly Guid TSATTRID_Text_Para_LineSpacing_AtLeast = new Guid(0xadfedf31, 0x2d44, 0x4434, 0xa5, 0xff, 0x7f, 0x4c, 0x49, 0x90, 0xa9, 0x05); + /// + public static readonly Guid TSATTRID_Text_Para_LineSpacing_Exactly = new Guid(0x3d45ad40, 0x23de, 0x48d7, 0xa6, 0xb3, 0x76, 0x54, 0x20, 0xc6, 0x20, 0xcc); + /// + public static readonly Guid TSATTRID_Text_Para_LineSpacing_Multiple = new Guid(0x910f1e3c, 0xd6d0, 0x4f65, 0x8a, 0x3c, 0x42, 0xb4, 0xb3, 0x18, 0x68, 0xc5); + + /// + public static readonly Guid TSATTRID_List = new Guid(0x436d673b, 0x26f1, 0x4aee, 0x9e, 0x65, 0x8f, 0x83, 0xa4, 0xed, 0x48, 0x84); + /// + public static readonly Guid TSATTRID_List_LevelIndel = new Guid(0x7f7cc899, 0x311f, 0x487b, 0xad, 0x5d, 0xe2, 0xa4, 0x59, 0xe1, 0x2d, 0x42); + /// + public static readonly Guid TSATTRID_List_Type = new Guid(0xae3e665e, 0x4bce, 0x49e3, 0xa0, 0xfe, 0x2d, 0xb4, 0x7d, 0x3a, 0x17, 0xae); + /// + public static readonly Guid TSATTRID_List_Type_Bullet = new Guid(0xbccd77c5, 0x4c4d, 0x4ce2, 0xb1, 0x02, 0x55, 0x9f, 0x3b, 0x2b, 0xfc, 0xea); + /// + public static readonly Guid TSATTRID_List_Type_Arabic = new Guid(0x1338c5d6, 0x98a3, 0x4fa3, 0x9b, 0xd1, 0x7a, 0x60, 0xee, 0xf8, 0xe9, 0xe0); + /// + public static readonly Guid TSATTRID_List_Type_LowerLetter = new Guid(0x96372285, 0xf3cf, 0x491e, 0xa9, 0x25, 0x38, 0x32, 0x34, 0x7f, 0xd2, 0x37); + /// + public static readonly Guid TSATTRID_List_Type_UpperLetter = new Guid(0x7987b7cd, 0xce52, 0x428b, 0x9b, 0x95, 0xa3, 0x57, 0xf6, 0xf1, 0x0c, 0x45); + /// + public static readonly Guid TSATTRID_List_Type_LowerRoman = new Guid(0x90466262, 0x3980, 0x4b8e, 0x93, 0x68, 0x91, 0x8b, 0xd1, 0x21, 0x8a, 0x41); + /// + public static readonly Guid TSATTRID_List_Type_UpperRoman = new Guid(0x0f6ab552, 0x4a80, 0x467f, 0xb2, 0xf1, 0x12, 0x7e, 0x2a, 0xa3, 0xba, 0x9e); + + /// + public static readonly Guid TSATTRID_App = new Guid(0xa80f77df,0x4237,0x40e5,0x84,0x9c,0xb5,0xfa,0x51,0xc1,0x3a,0xc7); + /// + public static readonly Guid TSATTRID_App_IncorrectSpelling = new Guid(0xf42de43c,0xef12,0x430d,0x94,0x4c,0x9a,0x08,0x97,0x0a,0x25,0xd2); + /// + public static readonly Guid TSATTRID_App_IncorrectGrammar = new Guid(0xbd54e398,0xad03,0x4b74,0xb6,0xb3,0x5e,0xdb,0x19,0x99,0x63,0x88); +*/ + public static readonly Guid GUID_SYSTEM_FUNCTIONPROVIDER = new Guid("9a698bb0-0f21-11d3-8df1-00105a2799b5"); + + + #endregion Constants + + //------------------------------------------------------ + // + // Enums + // + //------------------------------------------------------ + + #region Enums + + /// + [Flags] + public enum PopFlags + { + /// + TF_POPF_ALL = 0x0001, + } + + /// + [Flags] + public enum CreateContextFlags + { + // TF_PLAINTEXTTSI is undocumented + } + + /// + public enum TsGravity + { + /// + TS_GR_BACKWARD = 0, + /// + TS_GR_FORWARD = 1, + }; + + /// + public enum TsShiftDir + { + /// + TS_SD_BACKWARD = 0, + /// + TS_SD_FORWARD = 1, + }; + + /// + [Flags] + public enum SetTextFlags + { + /// + TS_ST_CORRECTION = 0x1, + } + + /// + [Flags] + public enum InsertEmbeddedFlags + { + /// + TS_IE_CORRECTION = 0x1, + } + + /// + [Flags] + public enum InsertAtSelectionFlags + { + /// + TS_IAS_NOQUERY = 0x1, + /// + TS_IAS_QUERYONLY = 0x2, + } + + /// + [Flags] + public enum AdviseFlags + { + /// + TS_AS_TEXT_CHANGE = 0x01, + /// + TS_AS_SEL_CHANGE = 0x02, + /// + TS_AS_LAYOUT_CHANGE = 0x04, + /// + TS_AS_ATTR_CHANGE = 0x08, + /// + TS_AS_STATUS_CHANGE = 0x10, + } + + /// + [Flags] + public enum LockFlags + { + /// + TS_LF_SYNC = 0x1, + /// + TS_LF_READ = 0x2, + /// + TS_LF_WRITE = 0x4, + /// + TS_LF_READWRITE = 0x6, + } + + /// + [Flags] + public enum DynamicStatusFlags + { + /// + TS_SD_READONLY = 0x001, + /// + TS_SD_LOADING = 0x002, + } + + /// + [Flags] + public enum StaticStatusFlags + { + /// + TS_SS_DISJOINTSEL = 0x001, + /// + TS_SS_REGIONS = 0x002, + /// + TS_SS_TRANSITORY = 0x004, + /// + TS_SS_NOHIDDENTEXT = 0x008, + } + + /// + [Flags] + public enum AttributeFlags + { + /// + TS_ATTR_FIND_BACKWARDS = 0x0001, + /// + TS_ATTR_FIND_WANT_OFFSET = 0x0002, + /// + TS_ATTR_FIND_UPDATESTART = 0x0004, + /// + TS_ATTR_FIND_WANT_VALUE = 0x0008, + /// + TS_ATTR_FIND_WANT_END = 0x0010, + /// + TS_ATTR_FIND_HIDDEN = 0x0020, + } + + /// + [Flags] + public enum GetPositionFromPointFlags + { + /// + GXFPF_ROUND_NEAREST = 0x1, + /// + GXFPF_NEAREST = 0x2, + } + + /// + public enum TsActiveSelEnd + { + /// + TS_AE_NONE = 0, + /// + TS_AE_START = 1, + /// + TS_AE_END = 2, + } + + /// + public enum TsRunType + { + /// + TS_RT_PLAIN = 0, + /// + TS_RT_HIDDEN = 1, + /// + TS_RT_OPAQUE = 2, + } + + /// + [Flags] + public enum OnTextChangeFlags + { + /// + TS_TC_CORRECTION = 0x1, + } + + /// + public enum TsLayoutCode + { + /// + TS_LC_CREATE = 0, + /// + TS_LC_CHANGE = 1, + /// + TS_LC_DESTROY = 2 + } + + /// + public enum TfGravity + { + /// + TF_GR_BACKWARD = 0, + /// + TF_GR_FORWARD = 1, + }; + + /// + public enum TfShiftDir + { + /// + TF_SD_BACKWARD = 0, + /// + TF_SD_FORWARD = 1, + }; + + /// + public enum TfAnchor + { + /// + TF_ANCHOR_START = 0, + /// + TF_ANCHOR_END = 1, + } + + /// + public enum TF_DA_COLORTYPE + { + /// + TF_CT_NONE = 0, + /// + TF_CT_SYSCOLOR = 1, + /// + TF_CT_COLORREF = 2 + } + + /// + public enum TF_DA_LINESTYLE + { + /// + TF_LS_NONE = 0, + /// + TF_LS_SOLID = 1, + /// + TF_LS_DOT = 2, + /// + TF_LS_DASH = 3, + /// + TF_LS_SQUIGGLE = 4 + } + + /// + public enum TF_DA_ATTR_INFO + { + /// + TF_ATTR_INPUT = 0, + /// + TF_ATTR_TARGET_CONVERTED = 1, + /// + TF_ATTR_CONVERTED = 2, + /// + TF_ATTR_TARGET_NOTCONVERTED = 3, + /// + TF_ATTR_INPUT_ERROR = 4, + /// + TF_ATTR_FIXEDCONVERTED = 5, + /// + TF_ATTR_OTHER = -1 + } + + /// + [Flags] + public enum GetRenderingMarkupFlags + { + /// + TF_GRM_INCLUDE_PROPERTY = 1 + } + + /// + [Flags] + public enum FindRenderingMarkupFlags + { + /// + TF_FRM_INCLUDE_PROPERTY = 0x1, + /// + TF_FRM_BACKWARD = 0x2, + /// + TF_FRM_NO_CONTAINED = 0x4, + /// + TF_FRM_NO_RANGE = 0x8 + } + + /// + [Flags] + public enum ConversionModeFlags + { + /// + TF_CONVERSIONMODE_ALPHANUMERIC = 0x0000, + /// + TF_CONVERSIONMODE_NATIVE = 0x0001, + /// + TF_CONVERSIONMODE_KATAKANA = 0x0002, + /// + TF_CONVERSIONMODE_FULLSHAPE = 0x0008, + /// + TF_CONVERSIONMODE_ROMAN = 0x0010, + /// + TF_CONVERSIONMODE_CHARCODE = 0x0020, + /// + TF_CONVERSIONMODE_NOCONVERSION = 0x0100, + /// + TF_CONVERSIONMODE_EUDC = 0x0200, + /// + TF_CONVERSIONMODE_SYMBOL = 0x0400, + /// + TF_CONVERSIONMODE_FIXED = 0x0800, + } + + /// + [Flags] + public enum SentenceModeFlags + { + /// + TF_SENTENCEMODE_NONE = 0x0000, + /// + TF_SENTENCEMODE_PLAURALCLAUSE = 0x0001, + /// + TF_SENTENCEMODE_SINGLECONVERT = 0x0002, + /// + TF_SENTENCEMODE_AUTOMATIC = 0x0004, + /// + TF_SENTENCEMODE_PHRASEPREDICT = 0x0008, + /// + TF_SENTENCEMODE_CONVERSATION = 0x0010, + } + + /// + public enum TfCandidateResult + { + CAND_FINALIZED = 0x0, + CAND_SELECTED = 0x1, + CAND_CANCELED = 0x2, + } + + #endregion Enums + + //------------------------------------------------------ + // + // Structs + // + //------------------------------------------------------ + + #region Structs + + /// + [StructLayout(LayoutKind.Sequential)] + public struct POINT + { + /// + /// + /// + public int x; + /// + /// + /// + public int y; + } + + /// + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + /// + public int left; + /// + public int top; + /// + public int right; + /// + public int bottom; + +/* + /// + public static RECT FromXYWH(int x, int y, int width, int height) + { + return new RECT(x, y, x + width, y + height); + } + + /// + public bool IsEmpty + { + get + { + return left >= right || top >= bottom; + } + } +*/ + } + + /// + [StructLayout(LayoutKind.Sequential)] + public struct TS_STATUS + { + /// + public DynamicStatusFlags dynamicFlags; + /// + public StaticStatusFlags staticFlags; + } + + /// + [StructLayout(LayoutKind.Sequential)] + public struct TS_SELECTIONSTYLE + { + /// + public TsActiveSelEnd ase; + /// + [MarshalAs(UnmanagedType.Bool)] + public bool interimChar; + } + + /// + [StructLayout(LayoutKind.Sequential)] + public struct TS_SELECTION_ACP + { + /// + public int start; + /// + public int end; + /// + public TS_SELECTIONSTYLE style; + } + + /// + [StructLayout(LayoutKind.Sequential)] + public struct TS_RUNINFO + { + /// + public int count; + /// + public TsRunType type; + } + + /// + [StructLayout(LayoutKind.Sequential)] + public struct TS_TEXTCHANGE + { + /// + public int start; + /// + public int oldEnd; + /// + public int newEnd; + } + + /// + [StructLayout(LayoutKind.Sequential)] + public struct TS_ATTRVAL + { + /// + public Guid attributeId; + + /// + public Int32 overlappedId; + + // Let val's offset 0x18. Though default pack is 8... + /// + public Int32 reserved; + + /// + [MarshalAs(UnmanagedType.Struct)] + public NativeMethods.VARIANT val; + } + + /// + [StructLayout(LayoutKind.Sequential)] + public struct TF_PRESERVEDKEY + { + /// + public int vKey; + /// + public int modifiers; + } + + /// + [StructLayout(LayoutKind.Sequential)] + public struct TF_DA_COLOR + { + /// + public TF_DA_COLORTYPE type; + /// + public Int32 indexOrColorRef; // TF_CT_SYSCOLOR/TF_CT_COLORREF union + } + + /// + [StructLayout(LayoutKind.Sequential)] + public struct TF_DISPLAYATTRIBUTE + { + /// + public TF_DA_COLOR crText; + /// + public TF_DA_COLOR crBk; + /// + public TF_DA_LINESTYLE lsStyle; + /// + [MarshalAs(UnmanagedType.Bool)] + public bool fBoldLine; + /// + public TF_DA_COLOR crLine; + /// + public TF_DA_ATTR_INFO bAttr; + } + + /// + [StructLayout(LayoutKind.Sequential)] + public struct TF_RENDERINGMARKUP + { + /// + /// + /// Critical: Field to critical type ITfRange + /// + [SecurityCritical] + public ITfRange range; + /// + public TF_DISPLAYATTRIBUTE tfDisplayAttr; + } + + /// + [StructLayout(LayoutKind.Sequential)] + internal struct TF_LANGUAGEPROFILE + { + internal Guid clsid; // CLSID of tip + internal short langid; // language id + internal Guid catid; // category of tip + [MarshalAs(UnmanagedType.Bool)] + internal bool fActive; // activated profile + internal Guid guidProfile; // profile description + } + + + #endregion Structs + + //------------------------------------------------------ + // + // Interfaces + // + //------------------------------------------------------ + + #region Interfaces + + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("8f1b8ad8-0b6b-4874-90c5-bd76011e8f7c")] + [System.Security.SuppressUnmanagedCodeSecurity] + internal interface ITfMessagePump + { + //HRESULT PeekMessageA([out] LPMSG pMsg, + // [in] HWND hwnd, + // [in] UINT wMsgFilterMin, + // [in] UINT wMsgFilterMax, + // [in] UINT wRemoveMsg, + // [out] BOOL *pfResult); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void PeekMessageA(ref System.Windows.Interop.MSG msg, + IntPtr hwnd, + int msgFilterMin, + int msgFilterMax, + int removeMsg, + out int result); + + //HRESULT GetMessageA([out] LPMSG pMsg, + // [in] HWND hwnd, + // [in] UINT wMsgFilterMin, + // [in] UINT wMsgFilterMax, + // [out] BOOL *pfResult); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetMessageA(ref System.Windows.Interop.MSG msg, + IntPtr hwnd, + int msgFilterMin, + int msgFilterMax, + out int result); + + //HRESULT PeekMessageW([out] LPMSG pMsg, + // [in] HWND hwnd, + // [in] UINT wMsgFilterMin, + // [in] UINT wMsgFilterMax, + // [in] UINT wRemoveMsg, + // [out] BOOL *pfResult); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void PeekMessageW(ref System.Windows.Interop.MSG msg, + IntPtr hwnd, + int msgFilterMin, + int msgFilterMax, + int removeMsg, + out int result); + + //HRESULT GetMessageW([out] LPMSG pMsg, + // [in] HWND hwnd, + // [in] UINT wMsgFilterMin, + // [in] UINT wMsgFilterMax, + // [out] BOOL *pfResult); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetMessageW(ref System.Windows.Interop.MSG msg, + IntPtr hwnd, + int msgFilterMin, + int msgFilterMax, + out int result); + }; + + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("e2449660-9542-11d2-bf46-00105a2799b5")] + public interface ITfProperty /* : ITfReadOnlyProperty */ + { + /// + //HRESULT GetType([out] GUID *pguid); + void GetType(out Guid type); + + /// + //HRESULT EnumRanges([in] TfEditCookie ec, + // [out] IEnumTfRanges **ppEnum, + // [in] ITfRange *pTargetRange); + [PreserveSig] + int EnumRanges(int editcookie, out IEnumTfRanges ranges, ITfRange targetRange); + + /// + //HRESULT GetValue([in] TfEditCookie ec, + // [in] ITfRange *pRange, + // [out] VARIANT *pvarValue); + void GetValue(int editCookie, ITfRange range, out object value); + + /// + //HRESULT GetContext([out] ITfContext **ppContext); + void GetContext(out ITfContext context); + + /// + //HRESULT FindRange([in] TfEditCookie ec, + // [in] ITfRange *pRange, + // [out] ITfRange **ppRange, + // [in] TfAnchor aPos); + void FindRange(int editCookie, ITfRange inRange, out ITfRange outRange, TfAnchor position); + + /// + //HRESULT SetValueStore([in] TfEditCookie ec, + // [in] ITfRange *pRange, + // [in] ITfPropertyStore *pPropStore); + void stub_SetValueStore(); + + /// + //HRESULT SetValue([in] TfEditCookie ec, + // [in] ITfRange *pRange, + // [in] const VARIANT *pvarValue); + void SetValue(int editCookie, ITfRange range, object value); + + /// + //HRESULT Clear([in] TfEditCookie ec, + // [in] ITfRange *pRange); + void Clear(int editCookie, ITfRange range); + } + + /// + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("aa80e7fd-2021-11d2-93e0-0060b067b86e")] + public interface ITfContext + { + //const DWORD TF_ES_ASYNCDONTCARE = 0x0; + //const DWORD TF_ES_SYNC = 0x1; + //const DWORD TF_ES_READ = 0x2; + //const DWORD TF_ES_READWRITE = 0x6; + //const DWORD TF_ES_ASYNC = 0x8; + + /// + //HRESULT RequestEditSession([in] TfClientId tid, + // [in] ITfEditSession *pes, + // [in] DWORD dwFlags, + // [out] HRESULT *phrSession); + int stub_RequestEditSession(); + + /// + //HRESULT InWriteSession([in] TfClientId tid, + // [out] BOOL *pfWriteSession); + void InWriteSession(int clientId, [MarshalAs(UnmanagedType.Bool)] out bool inWriteSession); + + //typedef [uuid(1690be9b-d3e9-49f6-8d8b-51b905af4c43)] enum { TF_AE_NONE = 0, TF_AE_START = 1, TF_AE_END = 2 } TfActiveSelEnd; + + //typedef [uuid(36ae42a4-6989-4bdc-b48a-6137b7bf2e42)] struct TF_SELECTIONSTYLE + //{ + // TfActiveSelEnd ase; + // BOOL fInterimChar; + //} TF_SELECTIONSTYLE; + + //typedef [uuid(75eb22f2-b0bf-46a8-8006-975a3b6efcf1)] struct TF_SELECTION + //{ + // ITfRange *range; + // TF_SELECTIONSTYLE style; + //} TF_SELECTION; + + //const ULONG TF_DEFAULT_SELECTION = TS_DEFAULT_SELECTION; + + /// + //HRESULT GetSelection([in] TfEditCookie ec, + // [in] ULONG ulIndex, + // [in] ULONG ulCount, + // [out, size_is(ulCount), length_is(*pcFetched)] TF_SELECTION *pSelection, + // [out] ULONG *pcFetched); + void stub_GetSelection(); + + /// + //HRESULT SetSelection([in] TfEditCookie ec, + // [in] ULONG ulCount, + // [in, size_is(ulCount)] const TF_SELECTION *pSelection); + void stub_SetSelection(); + + //HRESULT GetStart([in] TfEditCookie ec, + // [out] ITfRange **ppStart); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void GetStart(int ec, out ITfRange range); + + /// + //HRESULT GetEnd([in] TfEditCookie ec, + // [out] ITfRange **ppEnd); + void stub_GetEnd(); + + // bit values for TF_STATUS's dwDynamicFlags field + //const DWORD TF_SD_READONLY = TS_SD_READONLY; // if set, document is read only; writes will fail + //const DWORD TF_SD_LOADING = TS_SD_LOADING; // if set, document is loading, expect additional inserts + // bit values for TF_STATUS's dwStaticFlags field + //const DWORD TF_SS_DISJOINTSEL = TS_SS_DISJOINTSEL; // if set, the document supports multiple selections + //const DWORD TF_SS_REGIONS = TS_SS_REGIONS; // if clear, the document will never contain multiple regions + //const DWORD TF_SS_TRANSITORY = TS_SS_TRANSITORY; // if set, the document is expected to have a short lifespan + + //typedef [uuid(bc7d979a-846a-444d-afef-0a9bfa82b961)] TS_STATUS TF_STATUS; + + /// + //HRESULT GetActiveView([out] ITfContextView **ppView); + void stub_GetActiveView(); + + /// + //HRESULT EnumViews([out] IEnumTfContextViews **ppEnum); + void stub_EnumViews(); + + /// + //HRESULT GetStatus([out] TF_STATUS *pdcs); + void stub_GetStatus(); + + //HRESULT GetProperty([in] REFGUID guidProp, + // [out] ITfProperty **ppProp); + /// + /// Critical: COM interop call + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void GetProperty(ref Guid guid, out ITfProperty property); + + /// + //HRESULT GetAppProperty([in] REFGUID guidProp, + // [out] ITfReadOnlyProperty **ppProp); + void stub_GetAppProperty(); + + /// + //HRESULT TrackProperties([in, size_is(cProp)] const GUID **prgProp, + // [in] ULONG cProp, + // [in, size_is(cAppProp)] const GUID **prgAppProp, + // [in] ULONG cAppProp, + // [out] ITfReadOnlyProperty **ppProperty); + void stub_TrackProperties(); + + /// + //HRESULT EnumProperties([out] IEnumTfProperties **ppEnum); + void stub_EnumProperties(); + + /// + //HRESULT GetDocumentMgr([out] ITfDocumentMgr **ppDm); + void stub_GetDocumentMgr(); + + /// + //HRESULT CreateRangeBackup([in] TfEditCookie ec, + // [in] ITfRange *pRange, + // [out] ITfRangeBackup **ppBackup); + void stub_CreateRangeBackup(); + } + + /// + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("aa80e7f4-2021-11d2-93e0-0060b067b86e")] + [SuppressUnmanagedCodeSecurity] + public interface ITfDocumentMgr + { + // + //HRESULT CreateContext([in] TfClientId tidOwner, + // [in] DWORD dwFlags, + // [in, unique] IUnknown *punk, + // [out] ITfContext **ppic, + // [out] TfEditCookie *pecTextStore); + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void CreateContext(int clientId, CreateContextFlags flags, [MarshalAs(UnmanagedType.Interface)] object obj, out ITfContext context, out int editCookie); + + // + //HRESULT Push([in] ITfContext *pic); + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void Push(ITfContext context); + + // + //HRESULT Pop([in] DWORD dwFlags); + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void Pop(PopFlags flags); + + /// + //HRESULT GetTop([out] ITfContext **ppic); + void GetTop(out ITfContext context); + + //HRESULT GetBase([out] ITfContext **ppic); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void GetBase(out ITfContext context); + + /// + //HRESULT EnumContexts([out] IEnumTfContexts **ppEnum); + void EnumContexts([MarshalAs(UnmanagedType.Interface)] out /*IEnumTfContexts*/ object enumContexts); + } + + /// + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("aa80e808-2021-11d2-93e0-0060b067b86e")] + [SuppressUnmanagedCodeSecurity] + public interface IEnumTfDocumentMgrs + { + } + + /// + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("101d6610-0990-11d3-8df0-00105a2799b5")] + [SuppressUnmanagedCodeSecurity] + public interface ITfFunctionProvider + { + /// + //HRESULT GetType([out] GUID *pguid); + void GetType(out Guid guid); + + /// + //HRESULT GetDescription([out] BSTR *pbstrDesc); + void GetDescription([MarshalAs(UnmanagedType.BStr)] out string desc); + + // HRESULT GetFunction([in] REFGUID rguid, + // [in] REFIID riid, + // [out, iid_is(riid)] IUnknown **ppunk); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [PreserveSig] + int GetFunction(ref Guid guid, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object obj); + } + + /// + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("db593490-098f-11d3-8df0-00105a2799b5")] + [SuppressUnmanagedCodeSecurity] + public interface ITfFunction + { + /// + //HRESULT GetDisplayName([out] BSTR *pbstrName); + void GetDisplayName([MarshalAs(UnmanagedType.BStr)] out string funcName ); + } + + /// + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("581f317e-fd9d-443f-b972-ed00467c5d40")] + [SuppressUnmanagedCodeSecurity] + public interface ITfCandidateString + { + // HRESULT GetString([out] BSTR *pbstr); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void GetString([MarshalAs(UnmanagedType.BStr)] out string funcName ); + + /// + // HRESULT GetIndex([out] ULONG *pnIndex); + void GetIndex(out int nIndex ); + } + + /// + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("a3ad50fb-9bdb-49e3-a843-6c76520fbf5d")] + [SuppressUnmanagedCodeSecurity] + public interface ITfCandidateList + { + /// + // HRESULT EnumCandidates([out] IEnumTfCandidates **ppEnum); + void EnumCandidates(out object enumCand); + + // HRESULT GetCandidate([in] ULONG nIndex, + // [out] ITfCandidateString **ppCand); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void GetCandidate(int nIndex, out ITfCandidateString candstring); + + // HRESULT GetCandidateNum([out] ULONG *pnCnt); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void GetCandidateNum(out int nCount); + + + // HRESULT SetResult([in] ULONG nIndex, + // [in] TfCandidateResult imcr); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void SetResult(int nIndex, TfCandidateResult result); + } + + + /// + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("4cea93c0-0a58-11d3-8df0-00105a2799b5")] + [SuppressUnmanagedCodeSecurity] + public interface ITfFnReconversion + { + /// + // HRESULT GetDisplayName([out] BSTR *pbstrName); + void GetDisplayName([MarshalAs(UnmanagedType.BStr)] out string funcName ); + + // HRESULT QueryRange([in] ITfRange *pRange, + // [in, out, unique] ITfRange **ppNewRange, + // [out] BOOL *pfConvertable); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [PreserveSig] + int QueryRange(ITfRange range, + out ITfRange newRange, + [MarshalAs(UnmanagedType.Bool)] out bool isConvertable); + + // HRESULT GetReconversion([in] ITfRange *pRange, + // [out] ITfCandidateList **ppCandList); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [PreserveSig] + int GetReconversion(ITfRange range, out ITfCandidateList candList); + + /// + /// HRESULT Reconvert([in] ITfRange *pRange); + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [PreserveSig] + int Reconvert(ITfRange range); + } + + /// + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("88f567c6-1757-49f8-a1b2-89234c1eeff9")] + [SuppressUnmanagedCodeSecurity] + public interface ITfFnConfigure + { + /// + // HRESULT GetDisplayName([out] BSTR *pbstrName); + void GetDisplayName([MarshalAs(UnmanagedType.BStr)] out string funcName ); + + /// + // HRESULT Show([in] HWND hwndParent, + // [in] LANGID langid, + // [in] REFGUID rguidProfile); + [PreserveSig] + int Show(IntPtr hwndParent, short langid, ref Guid guidProfile); + } + + /// + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("bb95808a-6d8f-4bca-8400-5390b586aedf")] + [SuppressUnmanagedCodeSecurity] + public interface ITfFnConfigureRegisterWord + { + /// + // HRESULT GetDisplayName([out] BSTR *pbstrName); + void GetDisplayName([MarshalAs(UnmanagedType.BStr)] out string funcName ); + + /// + // HRESULT Show([in] HWND hwndParent, + // [in] LANGID langid, + // [in] REFGUID rguidProfile, + // [in, unique] BSTR bstrRegistered); + [PreserveSig] + int Show(IntPtr hwndParent, + short langid, + ref Guid guidProfile, + [MarshalAs(UnmanagedType.BStr)] string bstrRegistered ); + } + + + #region SpeechCommands + +#if UNUSED + /// + // + // Speech command provider and related interfaces + // + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("8c5dac4f-083c-4b85-a4c9-71746048adca")] + [SuppressUnmanagedCodeSecurity] + public interface IEnumSpeechCommands + { + /// + //HRESULT Clone([out] IEnumSpeechCommands **ppEnum); + void Clone([MarshalAs(UnmanagedType.Interface)] out object obj); + + /// + //HRESULT Next([in] ULONG ulCount, + // [out, size_is(ulCount), length_is(*pcFetched)] WCHAR **pSpCmds, + // [out] ULONG *pcFetched); + [PreserveSig] + int Next(int count, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] string [] spCmds, out int fetched); + + /// + //HRESULT Reset(); + void Reset(); + + /// + //HRESULT Skip(ULONG ulCount); + [PreserveSig] + int Skip(int count); + } + + /// + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("38e09d4c-586d-435a-b592-c8a86691dec6")] + [SuppressUnmanagedCodeSecurity] + public interface ISpeechCommandProvider + { + /// + //HRESULT EnumSpeechCommands([in] LANGID langid, [out] IEnumSpeechCommands **ppEnum); + void EnumSpeechCommands(short langid, [MarshalAs(UnmanagedType.Interface)] out object obj); + + /// + //HRESULT ProcessCommand([in, size_is(cch)] const WCHAR *pszCommand, + // [in] ULONG cch, + // [in] LANGID langid); + void ProcessCommand([In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] char []command, int cch, short langid); + } + + /// + /// + /// Critical - performs an elevation. + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("fca6c349-a12f-43a3-8dd6-5a5a4282577b")] + [SuppressUnmanagedCodeSecurity] + public interface ITfFnCustomSpeechCommand + { + /// + // ITfFunction method + void GetDisplayName([MarshalAs(UnmanagedType.BStr)] out string funcName ); + + /// + //HRESULT SetSpeechCommandProvider([in] ISpeechCommandProvider *pspcmdProvider); + void SetSpeechCommandProvider([MarshalAs(UnmanagedType.Interface)] object obj /*ISpeechCommandProvider spcmdProvider*/); + } + +#endif // UNUSED + + #endregion SpeechCommands + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("e4b24db0-0990-11d3-8df0-00105a2799b5")] + [SuppressUnmanagedCodeSecurity] + public interface IEnumTfFunctionProviders + { + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("bb08f7a9-607a-4384-8623-056892b64371")] + public interface ITfCompartment + { + // + //HRESULT SetValue([in] TfClientId tid, + // [in] const VARIANT *pvarValue); + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [PreserveSig] + int SetValue(int tid, ref object varValue); + + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + void GetValue(out object varValue); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("743abd5f-f26d-48df-8cc5-238492419b64")] + [SuppressUnmanagedCodeSecurity] + public interface ITfCompartmentEventSink + { + /// + //HRESULT OnChange([in] REFGUID rguid); + void OnChange(ref Guid rguid); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("7dcf57ac-18ad-438b-824d-979bffb74b7c")] + [SuppressUnmanagedCodeSecurity] + public interface ITfCompartmentMgr + { + // + //HRESULT GetCompartment([in] REFGUID rguid, + // [out] ITfCompartment **ppcomp); + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void GetCompartment(ref Guid guid, out ITfCompartment comp); + + /// + //HRESULT ClearCompartment([in] TfClientId tid, + // [in] REFGUID rguid); + void ClearCompartment(int tid, Guid guid); + + /// + //HRESULT EnumCompartments([out] IEnumGUID **ppEnum); + void EnumCompartments(out object /*IEnumGUID*/ enumGuid); + } + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("aa80e801-2021-11d2-93e0-0060b067b86e")] + [SuppressUnmanagedCodeSecurity] + internal interface ITfThreadMgr + { + // + //HRESULT Activate([out] TfClientId *ptid); + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void Activate(out int clientId); + + // + //HRESULT Deactivate(); + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void Deactivate(); + + // + //HRESULT CreateDocumentMgr([out] ITfDocumentMgr **ppdim); + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void CreateDocumentMgr(out ITfDocumentMgr docMgr); + + /// + //HRESULT EnumDocumentMgrs([out] IEnumTfDocumentMgrs **ppEnum); + void EnumDocumentMgrs(out IEnumTfDocumentMgrs enumDocMgrs); + + /// + //HRESULT GetFocus([out] ITfDocumentMgr **ppdimFocus); + void GetFocus(out ITfDocumentMgr docMgr); + + // + //HRESULT SetFocus([in] ITfDocumentMgr *pdimFocus); + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void SetFocus(ITfDocumentMgr docMgr); + + /// + //HRESULT AssociateFocus([in] HWND hwnd, + // [in, unique] ITfDocumentMgr *pdimNew, + // [out] ITfDocumentMgr **ppdimPrev); + void AssociateFocus(IntPtr hwnd, ITfDocumentMgr newDocMgr, out ITfDocumentMgr prevDocMgr); + + /// + //HRESULT IsThreadFocus([out] BOOL *pfThreadFocus); + void IsThreadFocus([MarshalAs(UnmanagedType.Bool)] out bool isFocus); + + //HRESULT GetFunctionProvider([in] REFCLSID clsid, + // [out] ITfFunctionProvider **ppFuncProv); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [PreserveSig] + int GetFunctionProvider(ref Guid classId, out ITfFunctionProvider funcProvider); + + /// + //HRESULT EnumFunctionProviders([out] IEnumTfFunctionProviders **ppEnum); + void EnumFunctionProviders(out IEnumTfFunctionProviders enumProviders); + + //HRESULT GetGlobalCompartment([out] ITfCompartmentMgr **ppCompMgr); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void GetGlobalCompartment(out ITfCompartmentMgr compartmentMgr); + } + + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("28888fe3-c2a0-483a-a3ea-8cb1ce51ff3d")] + [SuppressUnmanagedCodeSecurity] + public interface ITextStoreACP + { + /// + //HRESULT AdviseSink([in] REFIID riid, + // [in, iid_is(riid)] IUnknown *punk, + // [in] DWORD dwMask); + void AdviseSink(ref Guid riid, [MarshalAs(UnmanagedType.Interface)] object obj, AdviseFlags flags); + + /// + //HRESULT UnadviseSink([in] IUnknown *punk); + void UnadviseSink([MarshalAs(UnmanagedType.Interface)] object obj); + + /// + //HRESULT RequestLock([in] DWORD dwLockFlags, + // [out] HRESULT *phrSession); + void RequestLock(LockFlags flags, out int hrSession); + + /// + //HRESULT GetStatus([out] TS_STATUS *pdcs); + void GetStatus(out TS_STATUS status); + + /// + //HRESULT QueryInsert([in] LONG acpTestStart, + // [in] LONG acpTestEnd, + // [in] ULONG cch, + // [out] LONG *pacpResultStart, + // [out] LONG *pacpResultEnd); + void QueryInsert(int start, int end, int cch, out int startResult, out int endResult); + + /// + //HRESULT GetSelection([in] ULONG ulIndex, + // [in] ULONG ulCount, + // [out, size_is(ulCount), length_is(*pcFetched)] TS_SELECTION_ACP *pSelection, + // [out] ULONG *pcFetched); + void GetSelection(int index, int count, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] TS_SELECTION_ACP []selection, out int fetched); + + /// + //HRESULT SetSelection([in] ULONG ulCount, + // [in, size_is(ulCount)] const TS_SELECTION_ACP *pSelection); + void SetSelection(int count, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] TS_SELECTION_ACP []selection); + + /// + //HRESULT GetText([in] LONG acpStart, + // [in] LONG acpEnd, + // [out, size_is(cchPlainReq), length_is(*pcchPlainRet)] WCHAR *pchPlain, + // [in] ULONG cchPlainReq, + // [out] ULONG *pcchPlainRet, + // [out, size_is(cRunInfoReq), length_is(*pcRunInfoRet)] TS_RUNINFO *prgRunInfo, + // [in] ULONG cRunInfoReq, + // [out] ULONG *pcRunInfoRet, + // [out] LONG *pacpNext); + void GetText(int start, int end, + [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char []text, + int cchReq, out int charsCopied, + [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=6)] TS_RUNINFO []runInfo, + int cRunInfoReq, out int cRunInfoRcv, + out int nextCp); + + /// + //HRESULT SetText([in] DWORD dwFlags, + // [in] LONG acpStart, + // [in] LONG acpEnd, + // [in, size_is(cch)] const WCHAR *pchText, + // [in] ULONG cch, + // [out] TS_TEXTCHANGE *pChange); + void SetText(SetTextFlags flags, int start, int end, + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=4)] char []text, + int cch, out TS_TEXTCHANGE change); + + /// + //HRESULT GetFormattedText([in] LONG acpStart, + // [in] LONG acpEnd, + // [out] IDataObject **ppDataObject); + void GetFormattedText(int start, int end, [MarshalAs(UnmanagedType.Interface)] out object obj); + + /// + //HRESULT GetEmbedded([in] LONG acpPos, + // [in] REFGUID rguidService, + // [in] REFIID riid, + // [out, iid_is(riid)] IUnknown **ppunk); + void GetEmbedded(int position, ref Guid guidService, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object obj); + + /// + //HRESULT QueryInsertEmbedded([in] const GUID *pguidService, + // [in] const FORMATETC *pFormatEtc, + // [out] BOOL *pfInsertable); + void QueryInsertEmbedded(ref Guid guidService, int /*ref Win32.FORMATETC*/ formatEtc, [MarshalAs(UnmanagedType.Bool)] out bool insertable); + + /// + //HRESULT InsertEmbedded([in] DWORD dwFlags, + // [in] LONG acpStart, + // [in] LONG acpEnd, + // [in] IDataObject *pDataObject, + // [out] TS_TEXTCHANGE *pChange); + void InsertEmbedded(InsertEmbeddedFlags flags, int start, int end, [MarshalAs(UnmanagedType.Interface)] object obj, out TS_TEXTCHANGE change); + + /// + //HRESULT InsertTextAtSelection([in] DWORD dwFlags, + // [in, size_is(cch)] const WCHAR *pchText, + // [in] ULONG cch, + // [out] LONG *pacpStart, + // [out] LONG *pacpEnd, + // [out] TS_TEXTCHANGE *pChange); + void InsertTextAtSelection(InsertAtSelectionFlags flags, + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] char []text, + int cch, + out int start, out int end, out TS_TEXTCHANGE change); + + /// + //HRESULT InsertEmbeddedAtSelection([in] DWORD dwFlags, + // [in] IDataObject *pDataObject, + // [out] LONG *pacpStart, + // [out] LONG *pacpEnd, + // [out] TS_TEXTCHANGE *pChange); + void InsertEmbeddedAtSelection(InsertAtSelectionFlags flags, [MarshalAs(UnmanagedType.Interface)] object obj, + out int start, out int end, out TS_TEXTCHANGE change); + + /// + //HRESULT RequestSupportedAttrs([in] DWORD dwFlags, + // [in] ULONG cFilterAttrs, + // [in, size_is(cFilterAttrs), unique] const TS_ATTRID *paFilterAttrs); + [PreserveSig] + int RequestSupportedAttrs(AttributeFlags flags, int count, + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] Guid []filterAttributes); + + /// + //HRESULT RequestAttrsAtPosition([in] LONG acpPos, + // [in] ULONG cFilterAttrs, + // [in, size_is(cFilterAttrs), unique] const TS_ATTRID *paFilterAttrs, + // [in] DWORD dwFlags); + [PreserveSig] + int RequestAttrsAtPosition(int position, int count, + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] Guid []filterAttributes, + AttributeFlags flags); + + /// + //HRESULT RequestAttrsTransitioningAtPosition([in] LONG acpPos, + // [in] ULONG cFilterAttrs, + // [in, size_is(cFilterAttrs), unique] const TS_ATTRID *paFilterAttrs, + // [in] DWORD dwFlags); + void RequestAttrsTransitioningAtPosition(int position, int count, + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] Guid []filterAttributes, + AttributeFlags flags); + + /// + //HRESULT FindNextAttrTransition([in] LONG acpStart, + // [in] LONG acpHalt, + // [in] ULONG cFilterAttrs, + // [in, size_is(cFilterAttrs), unique] const TS_ATTRID *paFilterAttrs, + // [in] DWORD dwFlags, + // [out] LONG *pacpNext, + // [out] BOOL *pfFound, + // [out] LONG *plFoundOffset); + void FindNextAttrTransition(int start, int halt, int count, + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] Guid []filterAttributes, + AttributeFlags flags, out int acpNext, [MarshalAs(UnmanagedType.Bool)] out bool found, out int foundOffset); + + /// + //HRESULT RetrieveRequestedAttrs([in] ULONG ulCount, + // [out, size_is(ulCount), length_is(*pcFetched)] TS_ATTRVAL *paAttrVals, + // [out] ULONG *pcFetched); + void RetrieveRequestedAttrs(int count, + [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] TS_ATTRVAL []attributeVals, + out int countFetched); + + /// + //HRESULT GetEnd([out] LONG *pacp); + void GetEnd(out int end); + + /// + //HRESULT GetActiveView([out] TsViewCookie *pvcView); + void GetActiveView(out int viewCookie); + + /// + //HRESULT GetACPFromPoint([in] TsViewCookie vcView, + // [in] const POINT *ptScreen, + // [in] DWORD dwFlags, [out] LONG *pacp); + void GetACPFromPoint(int viewCookie, ref POINT point, GetPositionFromPointFlags flags, out int position); + + /// + //HRESULT GetTextExt([in] TsViewCookie vcView, + // [in] LONG acpStart, + // [in] LONG acpEnd, + // [out] RECT *prc, + // [out] BOOL *pfClipped); + void GetTextExt(int viewCookie, int start, int end, out RECT rect, [MarshalAs(UnmanagedType.Bool)] out bool clipped); + + /// + //HRESULT GetScreenExt([in] TsViewCookie vcView, + // [out] RECT *prc); + void GetScreenExt(int viewCookie, out RECT rect); + + /// + //HRESULT GetWnd([in] TsViewCookie vcView, + // [out] HWND *phwnd); + void GetWnd(int viewCookie, out IntPtr hwnd); + }; + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("22d44c94-a419-4542-a272-ae26093ececf")] + [SuppressUnmanagedCodeSecurity] + public interface ITextStoreACPSink + { + /// + /// + /// Critical - as this has SUC on it. + /// + //HRESULT OnTextChange([in] DWORD dwFlags, + // [in] const TS_TEXTCHANGE *pChange); + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void OnTextChange(OnTextChangeFlags flags, ref TS_TEXTCHANGE change); + + /// + /// + /// Critical - as this has SUC on it. + /// + //HRESULT OnSelectionChange(); + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void OnSelectionChange(); + + /// + /// + /// Critical - as this has SUC on it. + /// + //HRESULT OnLayoutChange([in] TsLayoutCode lcode, [in] TsViewCookie vcView); + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void OnLayoutChange(TsLayoutCode lcode, int viewCookie); + + /// + /// + /// Critical - as this has SUC on it. + /// + //HRESULT OnStatusChange([in] DWORD dwFlags); + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void OnStatusChange(DynamicStatusFlags flags); + + /// + /// + /// Critical - as this has SUC on it. + /// + //HRESULT OnAttrsChange([in] LONG acpStart, + // [in] LONG acpEnd, + // [in] ULONG cAttrs, + // [in, size_is(cAttrs)] const TS_ATTRID *paAttrs); + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void OnAttrsChange(int start, int end, int count, Guid[] attributes); + + /// + /// + /// Critical - as this has SUC on it. + /// + //HRESULT OnLockGranted([in] DWORD dwLockFlags); + [PreserveSig] + [SuppressUnmanagedCodeSecurity, SecurityCritical] + int OnLockGranted(LockFlags flags); + + /// + /// + /// Critical - as this has SUC on it. + /// + //HRESULT OnStartEditTransaction(); + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void OnStartEditTransaction(); + + /// + /// + /// Critical - as this has SUC on it. + /// + //HRESULT OnEndEditTransaction(); + [SuppressUnmanagedCodeSecurity, SecurityCritical] + void OnEndEditTransaction(); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("c0f1db0c-3a20-405c-a303-96b6010a885f")] + [SuppressUnmanagedCodeSecurity] + public interface ITfThreadFocusSink + { + /// + //HRESULT OnSetThreadFocus(); + void OnSetThreadFocus(); + + /// + //HRESULT OnKillThreadFocus(); + void OnKillThreadFocus(); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("4ea48a35-60ae-446f-8fd6-e6a8d82459f7")] + [SuppressUnmanagedCodeSecurity] + public interface ITfSource + { + // + //HRESULT AdviseSink([in] REFIID riid, + // [in, iid_is(riid)] IUnknown *punk, + // [out] DWORD *pdwCookie); + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void AdviseSink(ref Guid riid, [MarshalAs(UnmanagedType.Interface)] object obj, out int cookie); + + //HRESULT UnadviseSink([in] DWORD dwCookie); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void UnadviseSink(int cookie); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("aa80e7f0-2021-11d2-93e0-0060b067b86e")] + [SuppressUnmanagedCodeSecurity] + public interface ITfKeystrokeMgr + { + /// + //HRESULT AdviseKeyEventSink([in] TfClientId tid, + // [in] ITfKeyEventSink *pSink, + // [in] BOOL fForeground); + void AdviseKeyEventSink(int clientId, [MarshalAs(UnmanagedType.Interface)] object obj/*ITfKeyEventSink sink*/, [MarshalAs(UnmanagedType.Bool)] bool fForeground); + + /// + //HRESULT UnadviseKeyEventSink([in] TfClientId tid); + void UnadviseKeyEventSink(int clientId); + + /// + //HRESULT GetForeground([out] CLSID *pclsid); + void GetForeground(out Guid clsid); + + // + //HRESULT TestKeyDown([in] WPARAM wParam, + // [in] LPARAM lParam, + // [out] BOOL *pfEaten); + // int should be ok here, bit fields are well defined for this call as 32 bit, no pointers + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void TestKeyDown(int wParam, int lParam, [MarshalAs(UnmanagedType.Bool)] out bool eaten); + + // + //HRESULT TestKeyUp([in] WPARAM wParam, + // [in] LPARAM lParam, + // [out] BOOL *pfEaten); + // int should be ok here, bit fields are well defined for this call as 32 bit, no pointers + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void TestKeyUp(int wParam, int lParam, [MarshalAs(UnmanagedType.Bool)] out bool eaten); + + // + //HRESULT KeyDown([in] WPARAM wParam, + // [in] LPARAM lParam, + // [out] BOOL *pfEaten); + // int should be ok here, bit fields are well defined for this call as 32 bit, no pointers + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void KeyDown(int wParam, int lParam, [MarshalAs(UnmanagedType.Bool)] out bool eaten); + + // + //HRESULT KeyUp([in] WPARAM wParam, + // [in] LPARAM lParam, + // [out] BOOL *pfEaten); + // int should be ok here, bit fields are well defined for this call as 32 bit, no pointers + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void KeyUp(int wParam, int lParam, [MarshalAs(UnmanagedType.Bool)] out bool eaten); + + /// + //HRESULT GetPreservedKey([in] ITfContext *pic, + // [in] const TF_PRESERVEDKEY *pprekey, + // [out] GUID *pguid); + void GetPreservedKey(ITfContext context, ref TF_PRESERVEDKEY key, out Guid guid); + + /// + //HRESULT IsPreservedKey([in] REFGUID rguid, + // [in] const TF_PRESERVEDKEY *pprekey, + // [out] BOOL *pfRegistered); + void IsPreservedKey(ref Guid guid, ref TF_PRESERVEDKEY key, [MarshalAs(UnmanagedType.Bool)] out bool registered); + + /// + //HRESULT PreserveKey([in] TfClientId tid, + // [in] REFGUID rguid, + // [in] const TF_PRESERVEDKEY *prekey, + // [in, size_is(cchDesc)] const WCHAR *pchDesc, + // [in] ULONG cchDesc); + void PreserveKey(int clientId, ref Guid guid, ref TF_PRESERVEDKEY key, + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=4)] char []desc, int descCount); + + /// + //HRESULT UnpreserveKey([in] REFGUID rguid, + // [in] const TF_PRESERVEDKEY *pprekey); + void UnpreserveKey(ref Guid guid, ref TF_PRESERVEDKEY key); + + /// + //HRESULT SetPreservedKeyDescription([in] REFGUID rguid, + // [in, size_is(cchDesc)] const WCHAR *pchDesc, + // [in] ULONG cchDesc); + void SetPreservedKeyDescription(ref Guid guid, + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] char []desc, int descCount); + + /// + //HRESULT GetPreservedKeyDescription([in] REFGUID rguid, + // [out] BSTR *pbstrDesc); + void GetPreservedKeyDescription(ref Guid guid, [MarshalAs(UnmanagedType.BStr)] out string desc); + + /// + //HRESULT SimulatePreservedKey([in] ITfContext *pic, + // [in] REFGUID rguid, + // [out] BOOL *pfEaten); + void SimulatePreservedKey(ITfContext context, ref Guid guid, [MarshalAs(UnmanagedType.Bool)] out bool eaten); + }; + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("aa80e7ff-2021-11d2-93e0-0060b067b86e")] + public interface ITfRange + { + //const DWORD TF_HF_OBJECT = 1; // halt shift for TF_CHAR_EMBEDDED + //const DWORD TF_TF_MOVESTART = 1; // update start anchor + //const DWORD TF_TF_IGNOREEND = 2; // ignore the end anchor + //const DWORD TF_ST_CORRECTION = 1; // the replacement is a transform of existing content (correction), not new content + //const DWORD TF_IE_CORRECTION = 1; + + //typedef [uuid(49930d51-7d93-448c-a48c-fea5dac192b1)] struct TF_HALTCOND + //{ + // ITfRange *pHaltRange; // halt shift if anchor encountered + // TfAnchor aHaltPos; // ignored if pHaltRange == NULL + // DWORD dwFlags; // TF_HF_* + //} TF_HALTCOND; + + //HRESULT GetText([in] TfEditCookie ec, + // [in] DWORD dwFlags, + // [out, size_is(cchMax), length_is(*pcch)] WCHAR *pchText, + // [in] ULONG cchMax, + // [out] ULONG *pcch); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetText(int ec, /*GetTextFlags*/int flags, + [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char []text, + int countMax, out int count); + + //HRESULT SetText([in] TfEditCookie ec, + // [in] DWORD dwFlags, + // [in, size_is(cch), unique] const WCHAR *pchText, + // [in] LONG cch); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void SetText(int ec, /*SetTextFlags*/ int flags, + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char []text, + int count); + + //HRESULT GetFormattedText([in] TfEditCookie ec, + // [out] IDataObject **ppDataObject); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetFormattedText(int ec, [MarshalAs(UnmanagedType.Interface)] out object data); + + //HRESULT GetEmbedded([in] TfEditCookie ec, + // [in] REFGUID rguidService, + // [in] REFIID riid, + // [out, iid_is(riid)] IUnknown **ppunk); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetEmbedded(int ec, ref Guid guidService, ref Guid iid, [MarshalAs(UnmanagedType.Interface)] out object obj); + + //HRESULT InsertEmbedded([in] TfEditCookie ec, + // [in] DWORD dwFlags, + // [in] IDataObject *pDataObject); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void InsertEmbedded(int ec, int flags, [MarshalAs(UnmanagedType.Interface)] object data); + + //HRESULT ShiftStart([in] TfEditCookie ec, + // [in] LONG cchReq, + // [out] LONG *pcch, + // [in, unique] const TF_HALTCOND *pHalt); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ShiftStart(int ec, int count, out int result, int ZeroForNow); // todo: "ZeroForNow" should be a struct ptr if we ever use this + + //HRESULT ShiftEnd([in] TfEditCookie ec, + // [in] LONG cchReq, + // [out] LONG *pcch, + // [in, unique] const TF_HALTCOND *pHalt); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ShiftEnd(int ec, int count, out int result, int ZeroForNow); // todo: "ZeroForNow" should be a struct ptr if we ever use this + + //HRESULT ShiftStartToRange([in] TfEditCookie ec, + // [in] ITfRange *pRange, + // [in] TfAnchor aPos); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ShiftStartToRange(int ec, ITfRange range, TfAnchor position); + + //HRESULT ShiftEndToRange([in] TfEditCookie ec, + // [in] ITfRange *pRange, + // [in] TfAnchor aPos); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ShiftEndToRange(int ec, ITfRange range, TfAnchor position); + + //HRESULT ShiftStartRegion([in] TfEditCookie ec, + // [in] TfShiftDir dir, + // [out] BOOL *pfNoRegion); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ShiftStartRegion(int ec, TfShiftDir dir, [MarshalAs(UnmanagedType.Bool)] out bool noRegion); + + //HRESULT ShiftEndRegion([in] TfEditCookie ec, + // [in] TfShiftDir dir, + // [out] BOOL *pfNoRegion); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ShiftEndRegion(int ec, TfShiftDir dir, [MarshalAs(UnmanagedType.Bool)] out bool noRegion); + + //HRESULT IsEmpty([in] TfEditCookie ec, + // [out] BOOL *pfEmpty); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void IsEmpty(int ec, [MarshalAs(UnmanagedType.Bool)] out bool empty); + + //HRESULT Collapse([in] TfEditCookie ec, + // [in] TfAnchor aPos); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void Collapse(int ec, TfAnchor position); + + //HRESULT IsEqualStart([in] TfEditCookie ec, + // [in] ITfRange *pWith, + // [in] TfAnchor aPos, + // [out] BOOL *pfEqual); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void IsEqualStart(int ec, ITfRange with, TfAnchor position, [MarshalAs(UnmanagedType.Bool)] out bool equal); + + //HRESULT IsEqualEnd([in] TfEditCookie ec, + // [in] ITfRange *pWith, + // [in] TfAnchor aPos, + // [out] BOOL *pfEqual); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void IsEqualEnd(int ec, ITfRange with, TfAnchor position, [MarshalAs(UnmanagedType.Bool)] out bool equal); + + //HRESULT CompareStart([in] TfEditCookie ec, + // [in] ITfRange *pWith, + // [in] TfAnchor aPos, + // [out] LONG *plResult); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void CompareStart(int ec, ITfRange with, TfAnchor position, out int result); + + //HRESULT CompareEnd([in] TfEditCookie ec, + // [in] ITfRange *pWith, + // [in] TfAnchor aPos, + // [out] LONG *plResult); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void CompareEnd(int ec, ITfRange with, TfAnchor position, out int result); + + //HRESULT AdjustForInsert([in] TfEditCookie ec, + // [in] ULONG cchInsert, + // [out] BOOL *pfInsertOk); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void AdjustForInsert(int ec, int count, [MarshalAs(UnmanagedType.Bool)] out bool insertOk); + + //HRESULT GetGravity([out] TfGravity *pgStart, + // [out] TfGravity *pgEnd); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetGravity(out TfGravity start, out TfGravity end); + + //HRESULT SetGravity([in] TfEditCookie ec, + // [in] TfGravity gStart, + // [in] TfGravity gEnd); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void SetGravity(int ec, TfGravity start, TfGravity end); + + //HRESULT Clone([out] ITfRange **ppClone); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void Clone(out ITfRange clone); + + //HRESULT GetContext([out] ITfContext **ppContext); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetContext(out ITfContext context); + }; + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("057a6296-029b-4154-b79a-0d461d4ea94c")] + public interface ITfRangeACP /*: ITfRange*/ // derivation isn't working, calls to GetExtent go to ITfRange::GetText/vtbl[0] + { + //HRESULT GetText([in] TfEditCookie ec, + // [in] DWORD dwFlags, + // [out, size_is(cchMax), length_is(*pcch)] WCHAR *pchText, + // [in] ULONG cchMax, + // [out] ULONG *pcch); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetText(int ec, /*GetTextFlags*/int flags, + [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char []text, + int countMax, out int count); + + //HRESULT SetText([in] TfEditCookie ec, + // [in] DWORD dwFlags, + // [in, size_is(cch), unique] const WCHAR *pchText, + // [in] LONG cch); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void SetText(int ec, /*SetTextFlags*/ int flags, + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=3)] char []text, + int count); + + //HRESULT GetFormattedText([in] TfEditCookie ec, + // [out] IDataObject **ppDataObject); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetFormattedText(int ec, [MarshalAs(UnmanagedType.Interface)] out object data); + + //HRESULT GetEmbedded([in] TfEditCookie ec, + // [in] REFGUID rguidService, + // [in] REFIID riid, + // [out, iid_is(riid)] IUnknown **ppunk); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetEmbedded(int ec, ref Guid guidService, ref Guid iid, [MarshalAs(UnmanagedType.Interface)] out object obj); + + //HRESULT InsertEmbedded([in] TfEditCookie ec, + // [in] DWORD dwFlags, + // [in] IDataObject *pDataObject); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void InsertEmbedded(int ec, int flags, [MarshalAs(UnmanagedType.Interface)] object data); + + //HRESULT ShiftStart([in] TfEditCookie ec, + // [in] LONG cchReq, + // [out] LONG *pcch, + // [in, unique] const TF_HALTCOND *pHalt); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ShiftStart(int ec, int count, out int result, int ZeroForNow); // todo: "ZeroForNow" should be a struct ptr if we ever use this + + //HRESULT ShiftEnd([in] TfEditCookie ec, + // [in] LONG cchReq, + // [out] LONG *pcch, + // [in, unique] const TF_HALTCOND *pHalt); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ShiftEnd(int ec, int count, out int result, int ZeroForNow); // todo: "ZeroForNow" should be a struct ptr if we ever use this + + //HRESULT ShiftStartToRange([in] TfEditCookie ec, + // [in] ITfRange *pRange, + // [in] TfAnchor aPos); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ShiftStartToRange(int ec, ITfRange range, TfAnchor position); + + //HRESULT ShiftEndToRange([in] TfEditCookie ec, + // [in] ITfRange *pRange, + // [in] TfAnchor aPos); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ShiftEndToRange(int ec, ITfRange range, TfAnchor position); + + //HRESULT ShiftStartRegion([in] TfEditCookie ec, + // [in] TfShiftDir dir, + // [out] BOOL *pfNoRegion); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ShiftStartRegion(int ec, TfShiftDir dir, [MarshalAs(UnmanagedType.Bool)] out bool noRegion); + + //HRESULT ShiftEndRegion([in] TfEditCookie ec, + // [in] TfShiftDir dir, + // [out] BOOL *pfNoRegion); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ShiftEndRegion(int ec, TfShiftDir dir, [MarshalAs(UnmanagedType.Bool)] out bool noRegion); + + //HRESULT IsEmpty([in] TfEditCookie ec, + // [out] BOOL *pfEmpty); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void IsEmpty(int ec, [MarshalAs(UnmanagedType.Bool)] out bool empty); + + //HRESULT Collapse([in] TfEditCookie ec, + // [in] TfAnchor aPos); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void Collapse(int ec, TfAnchor position); + + //HRESULT IsEqualStart([in] TfEditCookie ec, + // [in] ITfRange *pWith, + // [in] TfAnchor aPos, + // [out] BOOL *pfEqual); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void IsEqualStart(int ec, ITfRange with, TfAnchor position, [MarshalAs(UnmanagedType.Bool)] out bool equal); + + //HRESULT IsEqualEnd([in] TfEditCookie ec, + // [in] ITfRange *pWith, + // [in] TfAnchor aPos, + // [out] BOOL *pfEqual); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void IsEqualEnd(int ec, ITfRange with, TfAnchor position, [MarshalAs(UnmanagedType.Bool)] out bool equal); + + //HRESULT CompareStart([in] TfEditCookie ec, + // [in] ITfRange *pWith, + // [in] TfAnchor aPos, + // [out] LONG *plResult); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void CompareStart(int ec, ITfRange with, TfAnchor position, out int result); + + //HRESULT CompareEnd([in] TfEditCookie ec, + // [in] ITfRange *pWith, + // [in] TfAnchor aPos, + // [out] LONG *plResult); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void CompareEnd(int ec, ITfRange with, TfAnchor position, out int result); + + //HRESULT AdjustForInsert([in] TfEditCookie ec, + // [in] ULONG cchInsert, + // [out] BOOL *pfInsertOk); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void AdjustForInsert(int ec, int count, [MarshalAs(UnmanagedType.Bool)] out bool insertOk); + + //HRESULT GetGravity([out] TfGravity *pgStart, + // [out] TfGravity *pgEnd); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetGravity(out TfGravity start, out TfGravity end); + + //HRESULT SetGravity([in] TfEditCookie ec, + // [in] TfGravity gStart, + // [in] TfGravity gEnd); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void SetGravity(int ec, TfGravity start, TfGravity end); + + //HRESULT Clone([out] ITfRange **ppClone); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void Clone(out ITfRange clone); + + //HRESULT GetContext([out] ITfContext **ppContext); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetContext(out ITfContext context); + + //HRESULT GetExtent([out] LONG *pacpAnchor, + // [out] LONG *pcch); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetExtent(out int start, out int count); + + //HRESULT SetExtent([in] LONG acpAnchor, + // [in] LONG cch); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void SetExtent(int start, int count); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("D7540241-F9A1-4364-BEFC-DBCD2C4395B7")] + public interface ITfCompositionView + { + //HRESULT GetOwnerClsid([out] CLSID *pclsid); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetOwnerClsid(out Guid clsid); + + //HRESULT GetRange([out] ITfRange **ppRange); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetRange(out ITfRange range); + }; + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("5F20AA40-B57A-4F34-96AB-3576F377CC79")] + [SuppressUnmanagedCodeSecurity] + public interface ITfContextOwnerCompositionSink + { + /// + //HRESULT OnStartComposition([in] ITfCompositionView *pComposition, + // [out] BOOL *pfOk); + void OnStartComposition(ITfCompositionView view, [MarshalAs(UnmanagedType.Bool)] out bool ok); + + /// + //HRESULT OnUpdateComposition([in] ITfCompositionView *pComposition, + // [in] ITfRange *pRangeNew); + void OnUpdateComposition(ITfCompositionView view, ITfRange rangeNew); + + /// + //HRESULT OnEndComposition([in] ITfCompositionView *pComposition); + void OnEndComposition(ITfCompositionView view); + }; + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("D40C8AAE-AC92-4FC7-9A11-0EE0E23AA39B")] + [SuppressUnmanagedCodeSecurity] + public interface ITfContextComposition + { + /// + //HRESULT StartComposition([in] TfEditCookie ecWrite, + // [in] ITfRange *pCompositionRange, + // [in] ITfCompositionSink *pSink, + // [out] ITfComposition **ppComposition); + void StartComposition(int ecWrite, ITfRange range, [MarshalAs(UnmanagedType.Interface)] object /*ITfCompositionSink */sink, [MarshalAs(UnmanagedType.Interface)] out object /*ITfComposition */composition); + + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + //HRESULT EnumCompositions([out] IEnumITfCompositionView **ppEnum); + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + void EnumCompositions([MarshalAs(UnmanagedType.Interface)] out IEnumITfCompositionView enumView); + + /// + //HRESULT FindComposition([in] TfEditCookie ecRead, + // [in] ITfRange *pTestRange, + // [out] IEnumITfCompositionView **ppEnum); + void FindComposition(int ecRead, ITfRange testRange, [MarshalAs(UnmanagedType.Interface)] out object /*IEnumITfCompositionView*/ enumView); + + /// + //HRESULT TakeOwnership([in] TfEditCookie ecWrite, + // [in] ITfCompositionView *pComposition, + // [in] ITfCompositionSink *pSink, + // [out] ITfComposition **ppComposition); + void TakeOwnership(int ecWrite, ITfCompositionView view, [MarshalAs(UnmanagedType.Interface)] object /*ITfCompositionSink */ sink, + [MarshalAs(UnmanagedType.Interface)] out object /*ITfComposition*/ composition); + }; + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("86462810-593B-4916-9764-19C08E9CE110")] + [SuppressUnmanagedCodeSecurity] + public interface ITfContextOwnerCompositionServices /*: ITfContextComposition*/ + { + /// + //HRESULT StartComposition([in] TfEditCookie ecWrite, + // [in] ITfRange *pCompositionRange, + // [in] ITfCompositionSink *pSink, + // [out] ITfComposition **ppComposition); + void StartComposition(int ecWrite, ITfRange range, [MarshalAs(UnmanagedType.Interface)] object /*ITfCompositionSink */sink, [MarshalAs(UnmanagedType.Interface)] out object /*ITfComposition */composition); + + /// + //HRESULT EnumCompositions([out] IEnumITfCompositionView **ppEnum); + void EnumCompositions([MarshalAs(UnmanagedType.Interface)] out object /*IEnumITfCompositionView*/ enumView); + + /// + //HRESULT FindComposition([in] TfEditCookie ecRead, + // [in] ITfRange *pTestRange, + // [out] IEnumITfCompositionView **ppEnum); + void FindComposition(int ecRead, ITfRange testRange, [MarshalAs(UnmanagedType.Interface)] out object /*IEnumITfCompositionView*/ enumView); + + /// + //HRESULT TakeOwnership([in] TfEditCookie ecWrite, + // [in] ITfCompositionView *pComposition, + // [in] ITfCompositionSink *pSink, + // [out] ITfComposition **ppComposition); + void TakeOwnership(int ecWrite, ITfCompositionView view, [MarshalAs(UnmanagedType.Interface)] object /*ITfCompositionSink */ sink, + [MarshalAs(UnmanagedType.Interface)] out object /*ITfComposition*/ composition); + + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + //HRESULT TerminateComposition([in] ITfCompositionView *pComposition); + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [PreserveSig] + int TerminateComposition(ITfCompositionView view); + }; + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("5EFD22BA-7838-46CB-88E2-CADB14124F8F")] + [SuppressUnmanagedCodeSecurity] + internal interface IEnumITfCompositionView + { + /// + //HRESULT Clone([out] IEnumTfRanges **ppEnum); + void Clone(out IEnumTfRanges ranges); + + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + //HRESULT Next([in] ULONG ulCount, + // [out, size_is(ulCount), length_is(*pcFetched)] ITfRange **ppRange, + // [out] ULONG *pcFetched); + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + [PreserveSig] + unsafe int Next(int count, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] ITfCompositionView []compositionview, out int fetched); + + /// + //HRESULT Reset(); + void Reset(); + + /// + //HRESULT Skip(ULONG ulCount); + [PreserveSig] + int Skip(int count); + } + + /// + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("f99d3f40-8e32-11d2-bf46-00105a2799b5")] + public interface IEnumTfRanges + { + //HRESULT Clone([out] IEnumTfRanges **ppEnum); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void Clone(out IEnumTfRanges ranges); + + //HRESULT Next([in] ULONG ulCount, + // [out, size_is(ulCount), length_is(*pcFetched)] ITfRange **ppRange, + // [out] ULONG *pcFetched); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + [PreserveSig] + unsafe int Next(int count, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] ITfRange []ranges, out int fetched); + + //HRESULT Reset(); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void Reset(); + + //HRESULT Skip(ULONG ulCount); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + [PreserveSig] + int Skip(int count); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("42d4d099-7c1a-4a89-b836-6c6f22160df0")] + [SuppressUnmanagedCodeSecurity] + public interface ITfEditRecord + { + //const DWORD TF_GTP_INCL_TEXT = 0x1; + + /// + //HRESULT GetSelectionStatus([out] BOOL *pfChanged); + void GetSelectionStatus([MarshalAs(UnmanagedType.Bool)] out bool selectionChanged); + + /// + //HRESULT GetTextAndPropertyUpdates([in] DWORD dwFlags, + // [in, size_is(cProperties)] const GUID **prgProperties, + // [in] ULONG cProperties, + // [out] IEnumTfRanges **ppEnum); + // + // TODO: yutakas + // + // Use "ref IntPtr" Temporarily. + // See the comment in InputMethodProperty.GetPropertyUpdate(). + // + unsafe void GetTextAndPropertyUpdates(int flags, + /*[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)]*/ /*Guid ** */ ref IntPtr properties, + int count, + out IEnumTfRanges ranges); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("8127d409-ccd3-4683-967a-b43d5b482bf7")] + [SuppressUnmanagedCodeSecurity] + public interface ITfTextEditSink + { + /// + //HRESULT OnEndEdit([in] ITfContext *pic, [in] TfEditCookie ecReadOnly, [in] ITfEditRecord *pEditRecord); + void OnEndEdit(ITfContext context, int ecReadOnly, ITfEditRecord editRecord); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("8c03d21b-95a7-4ba0-ae1b-7fce12a72930")] + [SuppressUnmanagedCodeSecurity] + public interface IEnumTfRenderingMarkup + { + /// + //HRESULT Clone([out] IEnumTfRenderingMarkup **ppClone); + void Clone(out IEnumTfRenderingMarkup clone); + + /// + //HRESULT Next([in] ULONG ulCount, + // [out, size_is(ulCount), length_is(*pcFetched)] TF_RENDERINGMARKUP *rgMarkup, + // [out] ULONG *pcFetched); + [PreserveSig] + int Next(int count, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] TF_RENDERINGMARKUP []markup, out int fetched); + + /// + //HRESULT Reset(); + void Reset(); + + /// + //HRESULT Skip([in] ULONG ulCount); + [PreserveSig] + int Skip(int count); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("a305b1c0-c776-4523-bda0-7c5a2e0fef10")] + [SuppressUnmanagedCodeSecurity] + public interface ITfContextRenderingMarkup + { + /// + //HRESULT GetRenderingMarkup([in] TfEditCookie ec, + // [in] DWORD dwFlags, + // [in] ITfRange *pRangeCover, + // [out] IEnumTfRenderingMarkup **ppEnum); + void GetRenderingMarkup(int editCookie, GetRenderingMarkupFlags flags, ITfRange range, out IEnumTfRenderingMarkup enumMarkup); + + /// + //HRESULT FindNextRenderingMarkup([in] TfEditCookie ec, + // [in] DWORD dwFlags, + // [in] ITfRange *pRangeQuery, + // [in] TfAnchor tfAnchorQuery, + // [out] ITfRange **ppRangeFound, + // [out] TF_RENDERINGMARKUP *ptfRenderingMarkup); + void FindNextRenderingMarkup(int editCookie, FindRenderingMarkupFlags flags, + ITfRange queryRange, TfAnchor queryAnchor, + out ITfRange foundRange, out TF_RENDERINGMARKUP foundMarkup); + } + + /// + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("1F02B6C5-7842-4EE6-8A0B-9A24183A95CA")] + public interface ITfInputProcessorProfiles + { + // HRESULT Register([in] REFCLSID rclsid); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_Register(); + + // HRESULT Unregister([in] REFCLSID rclsid); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_Unregister(); + + // HRESULT AddLanguageProfile([in] REFCLSID rclsid, + // [in] LANGID langid, + // [in] REFGUID guidProfile, + // [in, size_is(cchDesc)] const WCHAR *pchDesc, + // [in] ULONG cchDesc, + // [in, size_is(cchFile)] const WCHAR *pchIconFile, + // [in] ULONG cchFile, + // [in] ULONG uIconIndex); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_AddLanguageProfile(); + + // HRESULT RemoveLanguageProfile([in] REFCLSID rclsid, + // [in] LANGID langid, + // [in] REFGUID guidProfile); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_RemoveLanguageProfile(); + + // HRESULT EnumInputProcessorInfo([out] IEnumGUID **ppEnum); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_EnumInputProcessorInfo(); + + // HRESULT GetDefaultLanguageProfile([in] LANGID langid, + // [in] REFGUID catid, + // [out] CLSID *pclsid, + // [out] GUID *pguidProfile); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_GetDefaultLanguageProfile(); + + // HRESULT SetDefaultLanguageProfile([in] LANGID langid, + // [in] REFCLSID rclsid, + // [in] REFGUID guidProfiles); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_SetDefaultLanguageProfile(); + + // HRESULT ActivateLanguageProfile([in] REFCLSID rclsid, + // [in] LANGID langid, + // [in] REFGUID guidProfiles); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void ActivateLanguageProfile(ref Guid clsid, short langid, ref Guid guidProfile); + + // HRESULT GetActiveLanguageProfile([in] REFCLSID rclsid, + // [out] LANGID *plangid, + // [out] GUID *pguidProfile); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + [PreserveSig] + int GetActiveLanguageProfile(ref Guid clsid, out short langid, out Guid profile); + + // HRESULT GetLanguageProfileDescription([in] REFCLSID rclsid, + // [in] LANGID langid, + // [in] REFGUID guidProfile, + // [out] BSTR *pbstrProfile); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_GetLanguageProfileDescription(); + + // HRESULT GetCurrentLanguage([out] LANGID *plangid); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetCurrentLanguage(out short langid); + + // HRESULT ChangeCurrentLanguage([in] LANGID langid); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + [PreserveSig] + int ChangeCurrentLanguage(short langid); + + // HRESULT GetLanguageList([out] LANGID **ppLangId, + // [out] ULONG *pulCount); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + [PreserveSig] + int GetLanguageList(out IntPtr langids, out int count); + + + // HRESULT EnumLanguageProfiles([in] LANGID langid, + // [out] IEnumTfLanguageProfiles **ppEnum); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void EnumLanguageProfiles(short langid, out IEnumTfLanguageProfiles enumIPP); + + + // HRESULT EnableLanguageProfile([in] REFCLSID rclsid, + // [in] LANGID langid, + // [in] REFGUID guidProfile, + // [in] BOOL fEnable); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_EnableLanguageProfile(); + + // HRESULT IsEnabledLanguageProfile([in] REFCLSID rclsid, + // [in] LANGID langid, + // [in] REFGUID guidProfile, + // [out] BOOL *pfEnable); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_IsEnabledLanguageProfile(); + + // HRESULT EnableLanguageProfileByDefault([in] REFCLSID rclsid, + // [in] LANGID langid, + // [in] REFGUID guidProfile, + // [in] BOOL fEnable); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_EnableLanguageProfileByDefault(); + + // HRESULT SubstituteKeyboardLayout([in] REFCLSID rclsid, + // [in] LANGID langid, + // [in] REFGUID guidProfile, + // [in] HKL hKL); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_SubstituteKeyboardLayout(); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("3d61bf11-ac5f-42c8-a4cb-931bcc28c744")] + [SuppressUnmanagedCodeSecurity] + internal interface IEnumTfLanguageProfiles + { + /// + // HRESULT Clone([out] IEnumTfLanguageProfiles **ppEnum); + void Clone(out IEnumTfLanguageProfiles enumIPP); + + /// + // HRESULT Next([in] ULONG ulCount, + // [out, size_is(ulCount), length_is(*pcFetch)] TF_LANGUAGEPROFILE *pProfile, + // [out] ULONG *pcFetch); + [PreserveSig] + int Next(int count, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] TF_LANGUAGEPROFILE []profiles, out int fetched); + + /// + // HRESULT Reset(); + void Reset(); + + /// + // HRESULT Skip([in] ULONG ulCount); + void Skip(int count); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("43c9fe15-f494-4c17-9de2-b8a4ac350aa8")] + [SuppressUnmanagedCodeSecurity] + public interface ITfLanguageProfileNotifySink + { + /// + // HRESULT OnLanguageChange([in] LANGID langid, + // [out] BOOL *pfAccept); + void OnLanguageChange(short langid, [MarshalAs(UnmanagedType.Bool)] out bool bAccept); + + /// + // HRESULT OnLanguageChanged(); + void OnLanguageChanged(); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("8ded7393-5db1-475c-9e71-a39111b0ff67")] + public interface ITfDisplayAttributeMgr + { + // HRESULT OnUpdateInfo(); + // + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void OnUpdateInfo(); + + // HRESULT EnumDisplayAttributeInfo([out] IEnumTfDisplayAttributeInfo **ppEnum); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_EnumDisplayAttributeInfo(); + + // HRESULT GetDisplayAttributeInfo([in] REFGUID guid, + // [out] ITfDisplayAttributeInfo **ppInfo, + // [out] CLSID *pclsidOwner); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetDisplayAttributeInfo(ref Guid guid, out ITfDisplayAttributeInfo info, out Guid clsid); + + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("70528852-2f26-4aea-8c96-215150578932")] + public interface ITfDisplayAttributeInfo + { + // HRESULT GetGUID([out] GUID *pguid); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_GetGUID(); + + // HRESULT GetDescription([out] BSTR *pbstrDesc); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_GetDescription(); + + // HRESULT GetAttributeInfo([out] TF_DISPLAYATTRIBUTE *pda); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void GetAttributeInfo(out TF_DISPLAYATTRIBUTE attr); + + // HRESULT SetAttributeInfo([in] const TF_DISPLAYATTRIBUTE *pda); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_SetAttributeInfo(); + + // HRESULT Reset(); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_Reset(); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [SuppressUnmanagedCodeSecurity] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("c3acefb5-f69d-4905-938f-fcadcf4be830")] + public interface ITfCategoryMgr + { + // HRESULT RegisterCategory([in] REFCLSID rclsid, + // [in] REFGUID rcatid, + // [in] REFGUID rguid); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_RegisterCategory(); + + // HRESULT UnregisterCategory([in] REFCLSID rclsid, + // [in] REFGUID rcatid, + // [in] REFGUID rguid); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_UnregisterCategory(); + + // HRESULT EnumCategoriesInItem([in] REFGUID rguid, + // [out] IEnumGUID **ppEnum); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_EnumCategoriesInItem(); + + // HRESULT EnumItemsInCategory([in] REFGUID rcatid, + // [out] IEnumGUID **ppEnum); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_EnumItemsInCategory(); + + // HRESULT FindClosestCategory([in] REFGUID rguid, + // [out] GUID *pcatid, + // [in, size_is(ulCount)] const GUID **ppcatidList, + // [in] ULONG ulCount); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_FindClosestCategory(); + + // HRESULT RegisterGUIDDescription([in] REFCLSID rclsid, + // [in] REFGUID rguid, + // [in, size_is(cch)] const WCHAR *pchDesc, + // [in] ULONG cch); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_RegisterGUIDDescription(); + + // HRESULT UnregisterGUIDDescription([in] REFCLSID rclsid, + // [in] REFGUID rguid); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_UnregisterGUIDDescription(); + + // HRESULT GetGUIDDescription([in] REFGUID rguid, + // [out] BSTR *pbstrDesc); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_GetGUIDDescription(); + + // HRESULT RegisterGUIDDWORD([in] REFCLSID rclsid, + // [in] REFGUID rguid, + // [in] DWORD dw); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_RegisterGUIDDWORD(); + + // HRESULT UnregisterGUIDDWORD([in] REFCLSID rclsid, + // [in] REFGUID rguid); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_UnregisterGUIDDWORD(); + + // HRESULT GetGUIDDWORD([in] REFGUID rguid, + // [out] DWORD *pdw); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_GetGUIDDWORD(); + + // HRESULT RegisterGUID([in] REFGUID rguid, + // [out] TfGuidAtom *pguidatom); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_RegisterGUID(); + + // HRESULT GetGUID([in] TfGuidAtom guidatom, + // [out] GUID *pguid); + /// + /// + /// Critical - calls unmanaged code + /// + [PreserveSig] + [SecurityCritical] + int GetGUID(Int32 guidatom, out Guid guid); + + // HRESULT IsEqualTfGuidAtom([in] TfGuidAtom guidatom, + // [in] REFGUID rguid, + // [out] BOOL *pfEqual); + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical] + void stub_IsEqualTfGuidAtom(); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("aa80e80c-2021-11d2-93e0-0060b067b86e")] + [SuppressUnmanagedCodeSecurity] + public interface ITfContextOwner + { + /// + // HRESULT GetACPFromPoint([in] const POINT *ptScreen, + // [in] DWORD dwFlags, + // [out] LONG *pacp); + void GetACPFromPoint(ref POINT point, GetPositionFromPointFlags flags, out int position); + + /// + // HRESULT GetTextExt([in] LONG acpStart, + // [in] LONG acpEnd, + // [out] RECT *prc, + // [out] BOOL *pfClipped); + void GetTextExt(int start, int end, out RECT rect, [MarshalAs(UnmanagedType.Bool)] out bool clipped); + + /// + // HRESULT GetScreenExt([out] RECT *prc); + void GetScreenExt(out RECT rect); + + /// + // HRESULT GetStatus([out] TF_STATUS *pdcs); + void GetStatus(out TS_STATUS status); + + /// + // HRESULT GetWnd([out] HWND *phwnd); + void GetWnd(out IntPtr hwnd); + + /// + // HRESULT GetAttribute([in] REFGUID rguidAttribute, [out] VARIANT *pvarValue); + void GetValue(ref Guid guidAttribute, out object varValue); + } + + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("b23eb630-3e1c-11d3-a745-0050040ab407")] + [SuppressUnmanagedCodeSecurity] + public interface ITfContextOwnerServices + { + /// + // HRESULT OnLayoutChange(); + void stub_OnLayoutChange(); + + /// + // HRESULT OnStatusChange([in] DWORD dwFlags); + void stub_OnStatusChange(); + + /// + // HRESULT OnAttributeChange([in] REFGUID rguidAttribute); + void stub_OnAttributeChange(); + + /// + // HRESULT Serialize([in] ITfProperty *pProp, + // [in] ITfRange *pRange, + // [out] TF_PERSISTENT_PROPERTY_HEADER_ACP *pHdr, + // [in] IStream *pStream); + void stub_Serialize(); + + /// + // HRESULT Unserialize([in] ITfProperty *pProp, + // [in] const TF_PERSISTENT_PROPERTY_HEADER_ACP *pHdr, + // [in] IStream *pStream, + // [in] ITfPersistentPropertyLoaderACP *pLoader); + void stub_Unserialize(); + + /// + // HRESULT ForceLoadProperty([in] ITfProperty *pProp); + void stub_ForceLoadProperty(); + + /// + // HRESULT CreateRange([in] LONG acpStart, + // [in] LONG acpEnd, + // [out] ITfRangeACP **ppRange); + void CreateRange(Int32 acpStart, Int32 acpEnd, out ITfRangeACP range); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("a615096f-1c57-4813-8a15-55ee6e5a839c")] + [SuppressUnmanagedCodeSecurity] + public interface ITfTransitoryExtensionSink + { + /// + // HRESULT OnTransitoryExtensionUpdated([in] ITfContext *pic, + // [in] TfEditCookie ecReadOnly, + // [in] ITfRange *pResultRange, + // [in] ITfRange *pCompositionRange, + // [out] BOOL *pfDeleteResultRange); + void OnTransitoryExtensionUpdated(ITfContext context, int ecReadOnly, ITfRange rangeResult, ITfRange rangeComposition, [MarshalAs(UnmanagedType.Bool)] out bool fDeleteResultRange); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("fde1eaee-6924-4cdf-91e7-da38cff5559d")] + [SuppressUnmanagedCodeSecurity] + public interface ITfInputScope + { + /// + // HRESULT GetInputScopes([out] InputScope **pprgInputScopes, + // [out] UINT *pcCount); + void GetInputScopes(out IntPtr ppinputscopes, out int count); + + /// + // HRESULT GetPhrase([out] BSTR **ppbstrPhrases, + // [out] UINT *pcCount); + [PreserveSig] + int GetPhrase(out IntPtr ppbstrPhrases, out int count); + + /// + // HRESULT GetRegularExpression([out] BSTR *pbstrRegExp); + [PreserveSig] + int GetRegularExpression([Out, MarshalAs(UnmanagedType.BStr)] out string desc); + + /// + // HRESULT GetSRGS([out] BSTR *pbstrSRGS); + [PreserveSig] + int GetSRGC([Out, MarshalAs(UnmanagedType.BStr)] out string desc); + + /// + // HRESULT GetXML([out] BSTR *pbstrXML); + [PreserveSig] + int GetXML([Out, MarshalAs(UnmanagedType.BStr)] out string desc); + } + + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("3bdd78e2-c16e-47fd-b883-ce6facc1a208")] + [SuppressUnmanagedCodeSecurity] + public interface ITfMouseTrackerACP + { + /// + // HRESULT AdviseMouseSink([in] ITfRangeACP *range, + // [in] ITfMouseSink *pSink, + // [out] DWORD *pdwCookie); + [PreserveSig] + int AdviceMouseSink(ITfRangeACP range, ITfMouseSink sink, out int dwCookie); + + /// + // HRESULT UnadviseMouseSink([in] DWORD dwCookie); + [PreserveSig] + int UnadviceMouseSink(int dwCookie); + } + + /// + /// + /// Critical - calls unmanaged code + /// + [SecurityCritical(SecurityCriticalScope.Everything)] + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("a1adaaa2-3a24-449d-ac96-5183e7f5c217")] + [SuppressUnmanagedCodeSecurity] + public interface ITfMouseSink + { + // HRESULT OnMouseEvent([in] ULONG uEdge, + // [in] ULONG uQuadrant, + // [in] DWORD dwBtnStatus, + // [out] BOOL *pfEaten); + /// + /// + /// Critical: This code calls into an unmanaged COM function which is not + /// safe since it elevates + /// + [PreserveSig] + [SecurityCritical] + [SuppressUnmanagedCodeSecurity] + int OnMouseEvent(int edge, int quadrant, int btnStatus, [MarshalAs(UnmanagedType.Bool)] out bool eaten); + } + + #endregion Interfaces + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/WinInet.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/WinInet.cs new file mode 100644 index 00000000000..144ea42c07e --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/WinInet.cs @@ -0,0 +1,56 @@ +using System; +using System.Security; +using System.Runtime.InteropServices; + +namespace MS.Win32 +{ +internal static class WinInet +{ + /// + /// Will return the location of the internet cache folder. + /// + /// The location of the internet cache folder. + /// + /// Critical: + /// 1) Calls several Marshal methods which have a link demand on them. + /// 2) Calls NativeMethods.GetUrlCacheConfigInfo which is SecurityCritical. + /// Not Safe: + /// 2) Returns a Path that may leak information about the system. + /// + internal static Uri InternetCacheFolder + { + [SecurityCritical] + get + { + // copied value 260 from orginal implementation in BitmapDownload.cs + const int maxPathSize = 260; + const UInt32 fieldControl = (UInt32)maxPathSize; + + NativeMethods.InternetCacheConfigInfo icci = + new NativeMethods.InternetCacheConfigInfo(); + + icci.CachePath = new string(new char[maxPathSize]); + + UInt32 size = (UInt32)Marshal.SizeOf(icci); + icci.dwStructSize = size; + + bool passed = UnsafeNativeMethods.GetUrlCacheConfigInfo( + ref icci, + ref size, + fieldControl); + + if (!passed) + { + int hr = Marshal.GetHRForLastWin32Error(); + + if (hr != 0) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + return new Uri(icci.CachePath); + } + } +} +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/RefAssemblyAttrs.cs b/src/Microsoft.DotNet.Wpf/src/Shared/RefAssemblyAttrs.cs new file mode 100644 index 00000000000..d7e338dd4e4 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/RefAssemblyAttrs.cs @@ -0,0 +1,78 @@ +// DO NOT Edit this file w/o consulting with WPF Dev Manager +// +// The C++ version of these definitions is in inc\BuildInfo.hxx. + +using System; +using System.Text; + +#if WINDOWS_BASE +namespace MS.Internal.WindowsBase +#elif PRESENTATION_CORE +namespace MS.Internal.PresentationCore +#elif PRESENTATIONFRAMEWORK +namespace MS.Internal.PresentationFramework +#elif REACHFRAMEWORK +namespace MS.Internal.ReachFramework +#elif UIAUTOMATIONTYPES +namespace MS.Internal.UIAutomationTypes +#else +namespace Microsoft.Internal +#endif +{ + internal static class BuildInfo + { + internal const string WCP_PUBLIC_KEY_TOKEN = "31bf3856ad364e35"; + internal const string WCP_VERSION = "4.0.0.0"; + internal const string WCP_PUBLIC_KEY_STRING = "0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9"; + internal const string WCP_VERSION_SUFFIX = "_cor3"; + internal const string MIL_VERSION_SUFFIX = ""; + internal const string DEVDIV_PUBLIC_KEY_STRING = "00000000000000000400000000000000"; + internal const string DEVDIV_PUBLIC_KEY_TOKEN = "b77a5c561934e089"; + + // Constants to prevent hardcoding in InternalsVisibleTo attribute + internal const string PresentationCore = "PresentationCore, PublicKey="+ WCP_PUBLIC_KEY_STRING; + internal const string PresentationCFFRasterizer = "PresentationCFFRasterizer, PublicKey="+ WCP_PUBLIC_KEY_STRING; + internal const string PresentationFramework = "PresentationFramework, PublicKey="+ WCP_PUBLIC_KEY_STRING; + internal const string PresentationUI = "PresentationUI, PublicKey="+ WCP_PUBLIC_KEY_STRING; + internal const string PresentationFrameworkLuna = "PresentationFramework.Luna, PublicKey="+ WCP_PUBLIC_KEY_STRING; + internal const string PresentationFrameworkRoyale = "PresentationFramework.Royale, PublicKey="+ WCP_PUBLIC_KEY_STRING; + internal const string PresentationFrameworkAero = "PresentationFramework.Aero, PublicKey="+ WCP_PUBLIC_KEY_STRING; + internal const string PresentationFrameworkAero2 = "PresentationFramework.Aero2, PublicKey="+ WCP_PUBLIC_KEY_STRING; + internal const string PresentationFrameworkAeroLite = "PresentationFramework.AeroLite, PublicKey="+ WCP_PUBLIC_KEY_STRING; + internal const string PresentationFrameworkClassic = "PresentationFramework.Classic, PublicKey="+ WCP_PUBLIC_KEY_STRING; + internal const string PresentationFrameworkSystemCore = "PresentationFramework-SystemCore, PublicKey="+ DEVDIV_PUBLIC_KEY_STRING; + internal const string PresentationFrameworkSystemData = "PresentationFramework-SystemData, PublicKey="+ DEVDIV_PUBLIC_KEY_STRING; + internal const string PresentationFrameworkSystemDrawing = "PresentationFramework-SystemDrawing, PublicKey="+ DEVDIV_PUBLIC_KEY_STRING; + internal const string PresentationFrameworkSystemXml = "PresentationFramework-SystemXml, PublicKey="+ DEVDIV_PUBLIC_KEY_STRING; + internal const string PresentationFrameworkSystemXmlLinq = "PresentationFramework-SystemXmlLinq, PublicKey="+ DEVDIV_PUBLIC_KEY_STRING; + internal const string ReachFramework = "ReachFramework, PublicKey="+ WCP_PUBLIC_KEY_STRING; + internal const string SystemPrinting = "System.Printing, PublicKey="+ WCP_PUBLIC_KEY_STRING; + internal const string SystemXaml = "System.Xaml, PublicKey=" + DEVDIV_PUBLIC_KEY_STRING; + internal const string WindowsFormsIntegration = "WindowsFormsIntegration, PublicKey="+ WCP_PUBLIC_KEY_STRING; + + // Make internal visible to the 3.5 dll, System.Windows.Presentation.dll. + // we hard code the key here because the 3.5 dll is built in the devdiv depot using the CLR key. + internal const string SystemWindowsPresentation = "System.Windows.Presentation, PublicKey=" + DEVDIV_PUBLIC_KEY_STRING; + internal const string SystemWindowsControlsRibbon = "System.Windows.Controls.Ribbon, PublicKey=" + DEVDIV_PUBLIC_KEY_STRING; + } + + internal static class DllImport + { + internal const string PresentationNative = "PresentationNative" + BuildInfo.WCP_VERSION_SUFFIX + ".dll"; + internal const string PresentationCFFRasterizerNative = "PresentationCFFRasterizerNative" + BuildInfo.WCP_VERSION_SUFFIX + ".dll"; + internal const string MilCore = "wpfgfx" + BuildInfo.WCP_VERSION_SUFFIX + ".dll"; + + // DLL's w/o version suffix + internal const string UIAutomationCore = "UIAutomationCore.dll"; + internal const string Wininet = "Wininet.dll"; + internal const string WindowsCodecs = "WindowsCodecs.dll"; + internal const string WindowsCodecsExt = "WindowsCodecsExt.dll"; + internal const string Mscms = "mscms.dll"; + internal const string PrntvPt = "prntvpt.dll"; + internal const string Ole32 = "ole32.dll"; + internal const string User32 = "user32.dll"; + internal const string NInput = "ninput.dll"; + } +} + + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Ink/KnownIds.cs b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Ink/KnownIds.cs new file mode 100644 index 00000000000..4f248e661d1 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Ink/KnownIds.cs @@ -0,0 +1,324 @@ +using System; +using System.Collections; +using System.IO; +using MS.Internal.Ink.InkSerializedFormat; + +namespace System.Windows.Ink +{ + /// + /// DrawingAttributeIds + /// + public static class DrawingAttributeIds + { + /// + /// [To be supplied.] + /// + public static readonly Guid Color = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.ColorRef]; + /// + /// Guid identifying the StylusTip + /// + public static readonly Guid StylusTip = new Guid(0x3526c731, 0xee79, 0x4988, 0xb9, 0x3e, 0x70, 0xd9, 0x2f, 0x89, 0x7, 0xed); + /// + /// Guid identifying the StylusTipTransform + /// + public static readonly Guid StylusTipTransform = new Guid(0x4b63bc16, 0x7bc4, 0x4fd2, 0x95, 0xda, 0xac, 0xff, 0x47, 0x75, 0x73, 0x2d); + /// + /// The height of the pen tip which affects the stroke rendering. + /// + public static readonly Guid StylusHeight = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.StylusHeight]; + /// + /// The width of the pen tip which affects the stroke rendering. + /// + public static readonly Guid StylusWidth = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.StylusWidth]; + /// + /// [To be supplied.] + /// + public static readonly Guid DrawingFlags = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.DrawingFlags]; + /// + /// Guid identifying IsHighlighter + /// + public static readonly Guid IsHighlighter = new Guid(0xce305e1a, 0xe08, 0x45e3, 0x8c, 0xdc, 0xe4, 0xb, 0xb4, 0x50, 0x6f, 0x21); + } + + /// + /// [To be supplied.] + /// + internal static class KnownIds + { + #region Public Ids + /// + /// [To be supplied.] + /// + internal static readonly Guid X = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.X]; + /// + /// [To be supplied.] + /// + internal static readonly Guid Y = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.Y]; + /// + /// [To be supplied.] + /// + internal static readonly Guid Z = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.Z]; + /// + /// [To be supplied.] + /// + internal static readonly Guid PacketStatus = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.PacketStatus]; + /// + /// [To be supplied.] + /// + internal static readonly Guid TimerTick = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.TimerTick]; + /// + /// [To be supplied.] + /// + internal static readonly Guid SerialNumber = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.SerialNumber]; + /// + /// [To be supplied.] + /// + internal static readonly Guid NormalPressure = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.NormalPressure]; + /// + /// [To be supplied.] + /// + internal static readonly Guid TangentPressure = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.TangentPressure]; + /// + /// [To be supplied.] + /// + internal static readonly Guid ButtonPressure = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.ButtonPressure]; + /// + /// [To be supplied.] + /// + internal static readonly Guid XTiltOrientation = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.XTiltOrientation]; + /// + /// [To be supplied.] + /// + internal static readonly Guid YTiltOrientation = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.YTiltOrientation]; + /// + /// [To be supplied.] + /// + internal static readonly Guid AzimuthOrientation = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.AzimuthOrientation]; + /// + /// [To be supplied.] + /// + internal static readonly Guid AltitudeOrientation = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.AltitudeOrientation]; + /// + /// [To be supplied.] + /// + internal static readonly Guid TwistOrientation = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.TwistOrientation]; + /// + /// [To be supplied.] + /// + internal static readonly Guid PitchRotation = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.PitchRotation]; + /// + /// [To be supplied.] + /// + internal static readonly Guid RollRotation = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.RollRotation]; + /// + /// [To be supplied.] + /// + internal static readonly Guid YawRotation = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.YawRotation]; + /// + /// [To be supplied.] + /// + internal static readonly Guid Color = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.ColorRef]; + /// + /// [To be supplied.] + /// + internal static readonly Guid DrawingFlags = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.DrawingFlags]; + /// + /// [To be supplied.] + /// + internal static readonly Guid CursorId = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.CursorId]; + /// + /// [To be supplied.] + /// + internal static readonly Guid WordAlternates = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.WordAlternates]; + /// + /// [To be supplied.] + /// + internal static readonly Guid CharacterAlternates = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.CharAlternates]; + /// + /// [To be supplied.] + /// + internal static readonly Guid InkMetrics = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.InkMetrics]; + /// + /// [To be supplied.] + /// + internal static readonly Guid GuideStructure = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.GuideStructure]; + /// + /// [To be supplied.] + /// + internal static readonly Guid Timestamp = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.Timestamp]; + /// + /// [To be supplied.] + /// + internal static readonly Guid Language = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.Language]; + /// + /// [To be supplied.] + /// + internal static readonly Guid Transparency = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.Transparency]; + /// + /// [To be supplied.] + /// + internal static readonly Guid CurveFittingError = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.CurveFittingError]; + /// + /// [To be supplied.] + /// + internal static readonly Guid RecognizedLattice = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.RecoLattice]; + /// + /// [To be supplied.] + /// + internal static readonly Guid CursorDown = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.CursorDown]; + /// + /// [To be supplied.] + /// + internal static readonly Guid SecondaryTipSwitch = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.SecondaryTipSwitch]; + /// + /// [To be supplied.] + /// + internal static readonly Guid TabletPick = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.TabletPick]; + /// + /// [To be supplied.] + /// + internal static readonly Guid BarrelDown = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.BarrelDown]; + /// + /// [To be supplied.] + /// + internal static readonly Guid RasterOperation = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.RasterOperation]; + + /// + /// The height of the pen tip which affects the stroke rendering. + /// + internal static readonly Guid StylusHeight = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.StylusHeight]; + + /// + /// The width of the pen tip which affects the stroke rendering. + /// + internal static readonly Guid StylusWidth = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.StylusWidth]; + + /// + /// Guid identifying the highlighter property + /// + internal static readonly Guid Highlighter = KnownIdCache.TabletInternalIdTable[(int)KnownIdCache.TabletInternalIdIndex.Highlighter]; + /// + /// Guid identifying the Ink properties + /// + internal static readonly Guid InkProperties = KnownIdCache.TabletInternalIdTable[(int)KnownIdCache.TabletInternalIdIndex.InkProperties]; + /// + /// Guid identifying the Ink Style bold property + /// + internal static readonly Guid InkStyleBold = KnownIdCache.TabletInternalIdTable[(int)KnownIdCache.TabletInternalIdIndex.InkStyleBold]; + /// + /// Guid identifying the ink style italics property + /// + internal static readonly Guid InkStyleItalics = KnownIdCache.TabletInternalIdTable[(int)KnownIdCache.TabletInternalIdIndex.InkStyleItalics]; + /// + /// Guid identifying the stroke timestamp property + /// + internal static readonly Guid StrokeTimestamp = KnownIdCache.TabletInternalIdTable[(int)KnownIdCache.TabletInternalIdIndex.StrokeTimestamp]; + /// + /// Guid identifying the stroke timeid property + /// + internal static readonly Guid StrokeTimeId = KnownIdCache.TabletInternalIdTable[(int)KnownIdCache.TabletInternalIdIndex.StrokeTimeId]; + + /// + /// Guid identifying the StylusTip + /// + internal static readonly Guid StylusTip = new Guid(0x3526c731, 0xee79, 0x4988, 0xb9, 0x3e, 0x70, 0xd9, 0x2f, 0x89, 0x7, 0xed); + + /// + /// Guid identifying the StylusTipTransform + /// + internal static readonly Guid StylusTipTransform = new Guid(0x4b63bc16, 0x7bc4, 0x4fd2, 0x95, 0xda, 0xac, 0xff, 0x47, 0x75, 0x73, 0x2d); + + + /// + /// Guid identifying IsHighlighter + /// + internal static readonly Guid IsHighlighter = new Guid(0xce305e1a, 0xe08, 0x45e3, 0x8c, 0xdc, 0xe4, 0xb, 0xb4, 0x50, 0x6f, 0x21); + +// /// +// /// Guid used for identifying the fill-brush for rendering a stroke. +// /// +// public static readonly Guid FillBrush = new Guid(0x9a547c5c, 0x1fff, 0x4987, 0x8a, 0xb6, 0xbe, 0xed, 0x75, 0xde, 0xa, 0x1d); +// +// /// +// /// Guid used for identifying the pen used for rendering a stroke's outline. +// /// +// public static readonly Guid OutlinePen = new Guid(0x9967aea6, 0x3980, 0x4337, 0xb7, 0xc6, 0x34, 0xa, 0x33, 0x98, 0x8e, 0x6b); +// +// /// +// /// Guid used for identifying the blend mode used for rendering a stroke (similar to ROP in v1). +// /// +// public static readonly Guid BlendMode = new Guid(0xd6993943, 0x7a84, 0x4a80, 0x84, 0x68, 0xa8, 0x3c, 0xca, 0x65, 0xb0, 0x5); +// +// /// +// /// Guid used for identifying StylusShape object +// /// +// public static readonly Guid StylusShape = new Guid(0xf998e7f8, 0x7cdb, 0x4c0e, 0xb2, 0xe2, 0x63, 0x2b, 0xca, 0x21, 0x2a, 0x7b); + #endregion + + #region Internal Ids + + /// + /// The style of the rendering used for the pen tip. + /// + internal static readonly Guid PenStyle = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.PenStyle]; + + /// + /// The shape of the tip of the pen used for stroke rendering. + /// + internal static readonly Guid PenTip = KnownIdCache.OriginalISFIdTable[(int)KnownIdCache.OriginalISFIdIndex.PenTip]; + + /// + /// Guid used for identifying the Custom Stroke + /// + /// NTRAID#T2-17751-2003/11/26-stfisher: SPECISSUE: Should we hide the CustomStrokes and StrokeLattice data? + internal static readonly Guid InkCustomStrokes = KnownIdCache.TabletInternalIdTable[(int)KnownIdCache.TabletInternalIdIndex.InkCustomStrokes]; + + /// + /// Guid used for identifying the Stroke Lattice + /// + internal static readonly Guid InkStrokeLattice = KnownIdCache.TabletInternalIdTable[(int)KnownIdCache.TabletInternalIdIndex.InkStrokeLattice]; + +#if UNDO_ENABLED + /// + /// Guid used for identifying if an undo/event has already been handled + /// + /// {053BF717-DBE7-4e52-805E-64906138FAAD} + internal static readonly Guid UndoEventArgsHandled = new Guid(0x53bf717, 0xdbe7, 0x4e52, 0x80, 0x5e, 0x64, 0x90, 0x61, 0x38, 0xfa, 0xad); +#endif + #endregion + + #region Known Id Helpers + private static System.Reflection.MemberInfo[] PublicMemberInfo = null; + internal static string ConvertToString (Guid id) + { + + // Assert Reflection permissions shouldn't be required since we are only accessing public members + if (null == PublicMemberInfo) + { + PublicMemberInfo = typeof(KnownIds).FindMembers(System.Reflection.MemberTypes.Field, + System.Reflection.BindingFlags.Static | + System.Reflection.BindingFlags.GetField | + System.Reflection.BindingFlags.Instance | + System.Reflection.BindingFlags.Public | + System.Reflection.BindingFlags.Default, + null, null); + } + foreach (System.Reflection.MemberInfo info in PublicMemberInfo) + { + if ( id == (Guid)typeof(KnownIds).InvokeMember(info.Name, + System.Reflection.BindingFlags.Static | + System.Reflection.BindingFlags.GetField | + System.Reflection.BindingFlags.Instance | + System.Reflection.BindingFlags.Public | + System.Reflection.BindingFlags.Default, + null, null, new object[]{}, + System.Globalization.CultureInfo.InvariantCulture) ) + { + return info.Name; + } + } + return id.ToString(); + } + #endregion + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/InterOp/OSVersionHelper.cs b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/InterOp/OSVersionHelper.cs new file mode 100644 index 00000000000..f676dec20a1 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/InterOp/OSVersionHelper.cs @@ -0,0 +1,332 @@ +//--------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All rights reserved. +// +//--------------------------------------------------------------------------- + +#if WINDOWS_BASE +using MS.Internal.WindowsBase; +#elif PRESENTATION_CORE +using MS.Internal.PresentationCore; +#elif PRESENTATIONFRAMEWORK +using MS.Internal.PresentationFramework; +#elif REACHFRAMEWORK +using MS.Internal.ReachFramework; +#elif UIAUTOMATIONTYPES +using MS.Internal.UIAutomationTypes; +#else +using MS.Internal; +#endif + +using System; +using System.Runtime.InteropServices; +using System.Security; + +#if WINDOWS_BASE +namespace MS.Internal.WindowsBase.Interop +#elif PRESENTATION_CORE +namespace System.Windows.Interop +#elif PRESENTATIONFRAMEWORK +namespace MS.Internal.PresentationFramework.Interop +#elif REACHFRAMEWORK +namespace MS.Internal.ReachFramework.Interop +#elif UIAUTOMATIONTYPES +namespace MS.Internal.UIAutomationTypes.Interop +#else +namespace Microsoft.Internal.Interop +#endif +{ + /// + /// DevDiv:1158540 + /// Adding wrapper around OSVersionHelper native code. This is linked into PresentationNative so we just PInvoke it from there. + /// + /// To add a new OS: + /// Make sure you have followed the instructions in OperatingSystemVersion.cs to get here + /// Add appropriate PInvoke to your new Is{OSName}OrGreater function + /// Add case to switch statement in IsOsVersionOrGreater + /// Add new if statement to the TOP of GetOsVersion + /// + internal static class OSVersionHelper + { + #region Static OS Members + + internal static bool IsOsWindows10RS3OrGreater { get; set; } + + internal static bool IsOsWindows10RS2OrGreater { get; set; } + + internal static bool IsOsWindows10RS1OrGreater { get; set; } + + internal static bool IsOsWindows10TH2OrGreater { get; set; } + + internal static bool IsOsWindows10TH1OrGreater { get; set; } + + internal static bool IsOsWindows10OrGreater { get; set; } + + internal static bool IsOsWindows8Point1OrGreater { get; set; } + + internal static bool IsOsWindows8OrGreater { get; set; } + + internal static bool IsOsWindows7SP1OrGreater { get; set; } + + internal static bool IsOsWindows7OrGreater { get; set; } + + internal static bool IsOsWindowsVistaSP2OrGreater { get; set; } + + internal static bool IsOsWindowsVistaSP1OrGreater { get; set; } + + internal static bool IsOsWindowsVistaOrGreater { get; set; } + + internal static bool IsOsWindowsXPSP3OrGreater { get; set; } + + internal static bool IsOsWindowsXPSP2OrGreater { get; set; } + + internal static bool IsOsWindowsXPSP1OrGreater { get; set; } + + internal static bool IsOsWindowsXPOrGreater { get; set; } + + internal static bool IsOsWindowsServer { get; set; } + + #endregion + + #region Constructor + + [SecurityCritical] + static OSVersionHelper() + { + IsOsWindows10RS3OrGreater = IsWindows10RS3OrGreater(); + + IsOsWindows10RS2OrGreater = IsWindows10RS2OrGreater(); + + IsOsWindows10RS1OrGreater = IsWindows10RS1OrGreater(); + + IsOsWindows10TH2OrGreater = IsWindows10TH2OrGreater(); + + IsOsWindows10TH1OrGreater = IsWindows10TH1OrGreater(); + + IsOsWindows10OrGreater = IsWindows10OrGreater(); + + IsOsWindows8Point1OrGreater = IsWindows8Point1OrGreater(); + + IsOsWindows8OrGreater = IsWindows8OrGreater(); + + IsOsWindows7SP1OrGreater = IsWindows7SP1OrGreater(); + + IsOsWindows7OrGreater = IsWindows7OrGreater(); + + IsOsWindowsVistaSP2OrGreater = IsWindowsVistaSP2OrGreater(); + + IsOsWindowsVistaSP1OrGreater = IsWindowsVistaSP1OrGreater(); + + IsOsWindowsVistaOrGreater = IsWindowsVistaOrGreater(); + + IsOsWindowsXPSP3OrGreater = IsWindowsXPSP3OrGreater(); + + IsOsWindowsXPSP2OrGreater = IsWindowsXPSP2OrGreater(); + + IsOsWindowsXPSP1OrGreater = IsWindowsXPSP1OrGreater(); + + IsOsWindowsXPOrGreater = IsWindowsXPOrGreater(); + + IsOsWindowsServer = IsWindowsServer(); + } + + #endregion + + #region DLL Imports + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindows10RS3OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindows10RS2OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindows10RS1OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindows10TH2OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindows10TH1OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindows10OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindows8Point1OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindows8OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindows7SP1OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindows7OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindowsVistaSP2OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindowsVistaSP1OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindowsVistaOrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindowsXPSP3OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindowsXPSP2OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindowsXPSP1OrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindowsXPOrGreater(); + + [SecurityCritical, SuppressUnmanagedCodeSecurity] + [DllImport(DllImport.PresentationNative, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool IsWindowsServer(); + + #endregion + + #region Managed API + + internal static bool IsOsVersionOrGreater(OperatingSystemVersion osVer) + { + switch (osVer) + { + case OperatingSystemVersion.Windows10RS3: + return IsOsWindows10RS3OrGreater; + case OperatingSystemVersion.Windows10RS2: + return IsOsWindows10RS2OrGreater; + case OperatingSystemVersion.Windows10RS1: + return IsOsWindows10RS1OrGreater; + case OperatingSystemVersion.Windows10TH2: + return IsOsWindows10TH2OrGreater; + case OperatingSystemVersion.Windows10: + return IsOsWindows10OrGreater; + case OperatingSystemVersion.Windows8Point1: + return IsOsWindows8Point1OrGreater; + case OperatingSystemVersion.Windows8: + return IsOsWindows8OrGreater; + case OperatingSystemVersion.Windows7SP1: + return IsOsWindows7SP1OrGreater; + case OperatingSystemVersion.Windows7: + return IsOsWindows7OrGreater; + case OperatingSystemVersion.WindowsVistaSP2: + return IsOsWindowsVistaSP2OrGreater; + case OperatingSystemVersion.WindowsVistaSP1: + return IsOsWindowsVistaSP1OrGreater; + case OperatingSystemVersion.WindowsVista: + return IsOsWindowsVistaOrGreater; + case OperatingSystemVersion.WindowsXPSP3: + return IsOsWindowsXPSP3OrGreater; + case OperatingSystemVersion.WindowsXPSP2: + return IsOsWindowsXPSP2OrGreater; + } + + throw new ArgumentException(string.Format("{0} is not a valid OS!", osVer.ToString()), "osVer"); + } + + internal static OperatingSystemVersion GetOsVersion() + { + if (IsOsWindows10RS3OrGreater) + { + return OperatingSystemVersion.Windows10RS3; + } + else if (IsOsWindows10RS2OrGreater) + { + return OperatingSystemVersion.Windows10RS2; + } + else if (IsOsWindows10RS1OrGreater) + { + return OperatingSystemVersion.Windows10RS1; + } + else if (IsOsWindows10TH2OrGreater) + { + return OperatingSystemVersion.Windows10TH2; + } + else if (IsOsWindows10OrGreater) + { + return OperatingSystemVersion.Windows10; + } + else if (IsOsWindows8Point1OrGreater) + { + return OperatingSystemVersion.Windows8Point1; + } + else if (IsOsWindows8OrGreater) + { + return OperatingSystemVersion.Windows8; + } + else if (IsOsWindows7SP1OrGreater) + { + return OperatingSystemVersion.Windows7SP1; + } + else if (IsOsWindows7OrGreater) + { + return OperatingSystemVersion.Windows7; + } + else if (IsOsWindowsVistaSP2OrGreater) + { + return OperatingSystemVersion.WindowsVistaSP2; + } + else if (IsOsWindowsVistaSP1OrGreater) + { + return OperatingSystemVersion.WindowsVistaSP1; + } + else if (IsOsWindowsVistaOrGreater) + { + return OperatingSystemVersion.WindowsVista; + } + else if (IsOsWindowsXPSP3OrGreater) + { + return OperatingSystemVersion.WindowsXPSP3; + } + else if (IsOsWindowsXPSP2OrGreater) + { + return OperatingSystemVersion.WindowsXPSP2; + } + + throw new Exception("OSVersionHelper.GetOsVersion Could not detect OS!"); + } + + #endregion + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/InterOp/OperatingSystemVersion.cs b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/InterOp/OperatingSystemVersion.cs new file mode 100644 index 00000000000..481ad42f268 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/InterOp/OperatingSystemVersion.cs @@ -0,0 +1,52 @@ +//--------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All rights reserved. +// +//--------------------------------------------------------------------------- + +using System; + +#if WINDOWS_BASE +namespace MS.Internal.WindowsBase.Interop +#elif PRESENTATION_CORE +namespace System.Windows.Interop +#elif PRESENTATIONFRAMEWORK +namespace MS.Internal.PresentationFramework.Interop +#elif UIAUTOMATIONTYPES +namespace MS.Internal.UIAutomationTypes.Interop +#else +namespace Microsoft.Internal.Interop +#endif +{ + /// + /// This is not a complete list of operating system versions and service packs. + /// These are the interesting versions where features or behaviors were introduced + /// or changed, and code needs to detect those points and do different things. + /// + /// This list has been expanded in order to support our new OSVersionHelper lib. + /// + /// If you need to add an OS, do the following steps: + /// Create the appropriate native function in OSVersionHelper (see shared/OSVersionHelper/inc/OSVersionHelper.cpp) + /// Create the appropriate export in PresentationNative (see native/dll/dllentry.cpp) + /// Add it to the OperatingSystemVersion enumeration (Congrats, you're here already!) + /// Create the appropriate managed wrappers (see OSVersionHelper.cs) + /// Detect your freshly minted OS! + /// + internal enum OperatingSystemVersion + { + WindowsXPSP2, + WindowsXPSP3, + WindowsVista, + WindowsVistaSP1, + WindowsVistaSP2, + Windows7, + Windows7SP1, + Windows8, + Windows8Point1, + Windows10, + Windows10TH2, + Windows10RS1, + Windows10RS2, + Windows10RS3, + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/ReflectionHelper.cs b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/ReflectionHelper.cs new file mode 100644 index 00000000000..aa26201efe6 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/ReflectionHelper.cs @@ -0,0 +1,723 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Description: Specifies that the whitespace surrounding an element should be trimmed. +// + +using System; +using System.IO; +using System.Reflection; +using System.Diagnostics; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Runtime.CompilerServices; +using MS.Internal; + +#if PBTCOMPILER +using MS.Utility; +namespace MS.Internal.Markup + +#elif WINDOWS_BASE +using MS.Utility; +using MS.Internal.WindowsBase; +namespace System.Windows.Markup +#else +namespace System.Xaml +#endif +{ + + /// + /// Class that provides helper functions for the parser to reflect on types, properties, + /// custom attributes and load assemblies. + /// + internal static class ReflectionHelper + { + // System assembly name used by GetSystemType() to provide reflection + // types at markup compile time through System.Reflection.TypeLoader + private const string SystemReflectionAssemblyName = "System"; + + // TypeLoader core assembly name, also used by GetMscorlibType() to provide + // reflection types at markup compile time + private const string MscorlibReflectionAssemblyName = "mscorlib"; + +#if PBTCOMPILER + // System.Reflection.TypeLoader instance + private static TypeLoader _typeLoader = null; + + // TypeLoader Assembly cache + private static Dictionary _cachedTypeLoaderAssemblies = null; + + // TypeLoader reference paths + private static HashSet _cachedTypeLoaderReferencePaths = null; + + static ReflectionHelper() + { + // System.Reflection.TypeLoader Assembly cache + _cachedTypeLoaderAssemblies = new Dictionary(); + + // System.Reflection.TypeLoader assembly reference paths + _cachedTypeLoaderReferencePaths = new HashSet(); + + // Initializes the System.Reflection.TypeLoader instance + _typeLoader = new TypeLoader(MscorlibReflectionAssemblyName); + + // Attaches event handler that implements a probing strategy for + // locating assemblies or dependent assemblies requested by the + // TypeLoader in response to a reflection operation. + _typeLoader.Resolving += TypeLoaderResolvingHandler; + } +#endif + +#region Type + /// + /// Parse and get the type of the passed in string + /// + internal static Type GetQualifiedType(string typeName) + { + // ISSUE: we only parse the assembly name and type name + // all other Type.GetType() type fragments (version, culture info, pub key token etc) are ignored!!! + string[] nameFrags = typeName.Split(new Char[] { ',' }, 2); + Type type = null; + if (nameFrags.Length == 1) + { + // treat it as an absolute name + type = Type.GetType(nameFrags[0]); + } + else + { + if (nameFrags.Length != 2) + throw new InvalidOperationException(SR.Get(SRID.QualifiedNameHasWrongFormat, typeName)); + + Assembly a = null; + try + { + a = LoadAssembly(nameFrags[1].TrimStart(), null); + } + // ifdef magic to save compiler update. + // the fix below is for an FxCop rule about non-CLR exceptions. + // however this rule has now been removed. + catch (Exception e) // Load throws generic Exceptions, so this can't be made more specific. + { + if (CriticalExceptions.IsCriticalException(e)) + { + throw; + } + else + { + // If we can't load the assembly, just return null (fall-through). + a = null; + } + } + + if (a != null) + { + try + { + type = a.GetType(nameFrags[0]); + // If we can't get the type, just return null (fall-through). + } + catch (ArgumentException) + { + a = null; + } + catch (System.Security.SecurityException) + { + a = null; + } + } + } + + return type; + } + + internal static bool IsNullableType(Type type) + { + return (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable<>))); + } + + internal static bool IsInternalType(Type type) + { + Type origType = type; + Debug.Assert(null != type, "Type passed to IsInternalType is null"); + + // If this is an internal nested type or a parent nested public type, walk up the declaring types. + while (type.IsNestedAssembly || type.IsNestedFamORAssem || (origType != type && type.IsNestedPublic)) + { + type = type.DeclaringType; + } + + // If we're on a non-internal nested type, IsNotPublic & IsPublic will both return false. + // If we were originally on a nested type and have currently reached a parent + // top-level(non nested) type, then it must be top level internal or public type. + return type.IsNotPublic || (origType != type && type.IsPublic); + } + + /// + /// Helper for determine if the type is a public class. + /// + /// Type to check + /// True if type is public + internal static bool IsPublicType(Type type) + { + Debug.Assert(null != type, "Type passed to IsPublicType is null"); + + // If this is a nested internal type, walk up the declaring types. + while (type.IsNestedPublic) + { + type = type.DeclaringType; + } + + // If we're on a non-public nested type, IsPublic will return false. + return type.IsPublic; + } + + // Since assemblies may be loaded in regular load context as well ROL context + // we need to get the ROL type from the real type to compare a type with at compile + // time. At run-time, the same type can be used. + internal static Type GetFrameworkType(string assemblyName, Type type) + { +#if PBTCOMPILER + Assembly reflectionAssembly = LoadAssembly(assemblyName, null); + + if (reflectionAssembly != null) + { + type = reflectionAssembly.GetType(type.FullName); + } + else + { + type = null; + } +#endif + return type; + } + + internal static Type GetMscorlibType(Type type) + { + return GetFrameworkType(MscorlibReflectionAssemblyName, type); + } + + internal static Type GetSystemType(Type type) + { + return GetFrameworkType(SystemReflectionAssemblyName, type); + } + +#if WINDOWS_BASE + /// + /// Get the type to use for reflection: the custom type, if any, otherwise just the type. + /// + internal static Type GetReflectionType(object item) + { + if (item == null) + return null; + + ICustomTypeProvider ictp = item as ICustomTypeProvider; + if (ictp == null) + return item.GetType(); + else + return ictp.GetCustomType(); + } +#endif + +#endregion Type + + #region Attributes + + internal static string GetTypeConverterAttributeData(Type type, out Type converterType) + { + bool foundTC = false; + return GetCustomAttributeData(type, GetSystemType(typeof(TypeConverterAttribute)), true, ref foundTC, out converterType); + } + + internal static string GetTypeConverterAttributeData(MemberInfo mi, out Type converterType) + { + return GetCustomAttributeData(mi, GetSystemType(typeof(TypeConverterAttribute)), out converterType); + } + + // Given a ReflectionOnlyLoaded member, returns the value of a metadata attribute of + // Type attrType if set on that member. Looks only for attributes that have a ctor with + // one parameter that is of Type string or Type. + private static string GetCustomAttributeData(MemberInfo mi, Type attrType, out Type typeValue) + { + IList list = CustomAttributeData.GetCustomAttributes(mi); + string attrValue = GetCustomAttributeData(list, attrType, out typeValue, true, false); + return attrValue == null ? string.Empty : attrValue; + } + +#if PBTCOMPILER + // Given a ReflectionOnlyLoaded type, returns the value of a metadata attribute of + // Type attrType if set on that type. Looks only for attributes that have a ctor with + // one parameter that is of Type string. + internal static string GetCustomAttributeData(Type t, Type attrType, bool allowZeroArgs) + { + Type typeValue = null; + IList list = CustomAttributeData.GetCustomAttributes(t); + return GetCustomAttributeData(list, attrType, out typeValue, false, allowZeroArgs); + } +#endif + + // Helper that enumerates a list of CustomAttributeData obtained via ReflectionOnlyLoad, and + // looks for a specific attribute of Type attrType. It only looks for attribiutes with a single + // value of Type string that is passed in via a ctor. If allowTypeAlso is true, then it looks for + // values of typeof(Type) as well. + private static string GetCustomAttributeData(IList list, Type attrType, out Type typeValue, bool allowTypeAlso, bool allowZeroArgs) + { + typeValue = null; + string attrValue = null; + for (int j = 0; j < list.Count; j++) + { + attrValue = GetCustomAttributeData(list[j], attrType, out typeValue, allowTypeAlso, false, allowZeroArgs); + if (attrValue != null) + { + break; + } + } + + return attrValue; + } + + // Special version of type-based GetCustomAttributeData that does two + // additional tasks: + // 1) Retrieves the attributes even if it's defined on a base type, and + // 2) Distinguishes between "attribute found and said null" and + // "no attribute found at all" via the ref bool. + internal static string GetCustomAttributeData(Type t, + Type attrType, + bool allowTypeAlso, + ref bool attributeDataFound, + out Type typeValue) + { + typeValue = null; + attributeDataFound = false; + Type currentType = t; + string attributeDataString = null; + CustomAttributeData cad; + + while (currentType != null && !attributeDataFound) + { + IList list = CustomAttributeData.GetCustomAttributes(currentType); + + for (int j = 0; j < list.Count && !attributeDataFound; j++) + { + cad = list[j]; + + if (cad.Constructor.ReflectedType == attrType) + { + attributeDataFound = true; + attributeDataString = GetCustomAttributeData(cad, attrType, out typeValue, allowTypeAlso, false, false); + } + } + + if (!attributeDataFound) + { + currentType = currentType.BaseType; // object.BaseType is null, used as terminating condition for the while() loop. + } + } + + return attributeDataString; + } + + // Helper that inspects a specific CustomAttributeData obtained via ReflectionOnlyLoad, and + // returns its value if the Type of the attribiutes matches the passed in attrType. It only + // looks for attributes with no values or a single value of Type string that is passed in via + // a ctor. If allowTypeAlso is true, then it looks for values of typeof(Type) as well in the + // single value case. If noArgs == false and zeroArgsAllowed = true, that means 0 or 1 args + // are permissible. + private static string GetCustomAttributeData(CustomAttributeData cad, + Type attrType, + out Type typeValue, + bool allowTypeAlso, + bool noArgs, + bool zeroArgsAllowed) + { + string attrValue = null; + typeValue = null; + + // get the Constructor info + ConstructorInfo cinfo = cad.Constructor; + if (cinfo.ReflectedType == attrType) + { + // typedConstructorArguments (the Attribute constructor arguments) + // [MyAttribute("test", Name=Hello)] + // "test" is the Constructor Argument + IList constructorArguments = cad.ConstructorArguments; + if (constructorArguments.Count == 1 && !noArgs) + { + CustomAttributeTypedArgument tca = constructorArguments[0]; + attrValue = tca.Value as String; + if (attrValue == null && allowTypeAlso && tca.ArgumentType == typeof(Type)) + { + typeValue = tca.Value as Type; + attrValue = typeValue.AssemblyQualifiedName; + } + + if (attrValue == null) + { + throw new ArgumentException(SR.Get(SRID.ParserAttributeArgsLow, attrType.Name)); + } + } + else if (constructorArguments.Count == 0) + { + // zeroArgsAllowed = true for CPA for example. + // CPA with no args is valid and would mean that this type is overriding a base CPA + if (noArgs || zeroArgsAllowed) + { + attrValue = string.Empty; + } + else + { + throw new ArgumentException(SR.Get(SRID.ParserAttributeArgsLow, attrType.Name)); + } + } + else + { + throw new ArgumentException(SR.Get(SRID.ParserAttributeArgsHigh, attrType.Name)); + } + } + + return attrValue; + } + +#endregion Attributes + +#region Assembly Loading + // + // Clean up the cache entry for the given assembly, so that it can be reloaded for the next build cycle. + // Usually it is called by MarkupCompiler task. + // + internal static void ResetCacheForAssembly(string assemblyName) + { + string assemblyNameLookup = assemblyName.ToUpper(CultureInfo.InvariantCulture); +#if PBTCOMPILER + // TODO: PresentationBuildTasks porting : Reset TypeLoader between compile passes. + // Do not do this here, which will recreate the entire TypeLoader. There doesn't + // appear to be way to release a specific assembly in TypeLoader. + // + // Explicitly dispose and re-create the TypeLoader to release all assemblies. + // The intermediate assembly created by MarkupCompilePass1 is used as a reference + // and needs to be writable in compile pass 2. + _typeLoader.Dispose(); + _cachedTypeLoaderAssemblies.Clear(); + _cachedTypeLoaderReferencePaths.Clear(); + _typeLoader = new TypeLoader(); + _reflectionOnlyLoadedAssembliesHash[assemblyNameLookup] = null; +#else + _loadedAssembliesHash[assemblyNameLookup] = null; +#endif + } + + internal static Assembly LoadAssembly(string assemblyName, string assemblyPath) + { +#if PBTCOMPILER + return ReflectionOnlyLoadAssembly(assemblyName, assemblyPath); +#else + return LoadAssemblyHelper(assemblyName, assemblyPath); +#endif + } + +#if !PBTCOMPILER + internal static Assembly GetAlreadyLoadedAssembly(string assemblyNameLookup) + { + return (Assembly)_loadedAssembliesHash[assemblyNameLookup]; + } + + // Loads the Assembly with the specified name at the specified optional location. + // + // assemblyName is either short name or full name. + // assemblyPath is either full file path or null. + // + private static Assembly LoadAssemblyHelper(string assemblyGivenName, string assemblyPath) + { + AssemblyName assemblyName = new AssemblyName(assemblyGivenName); + string assemblyShortName = assemblyName.Name; + assemblyShortName = assemblyShortName.ToUpper(CultureInfo.InvariantCulture); + + // Check if the assembly has already been loaded. + Assembly retassem = (Assembly)_loadedAssembliesHash[assemblyShortName]; + + if (retassem != null) + { + if (assemblyName.Version != null) + { + AssemblyName cachedName = new AssemblyName(retassem.FullName); + if (!AssemblyName.ReferenceMatchesDefinition(assemblyName, cachedName)) + { + string request = assemblyName.ToString(); + string found = cachedName.ToString(); + throw new InvalidOperationException(SR.Get(SRID.ParserAssemblyLoadVersionMismatch, request, found)); + } + } + } + else + { + // Check if the current AppDomain has this assembly loaded for some other reason. + // If so, then just use that assembly and don't attempt to load another copy of it. + // Only do this if no path is provided. + if (String.IsNullOrEmpty(assemblyPath)) + retassem = SafeSecurityHelper.GetLoadedAssembly(assemblyName); + + if (retassem == null) + { + if (!String.IsNullOrEmpty(assemblyPath)) + { + + // assemblyPath is set, Load the assembly from this specified place. + // the path must be full file path which contains directory, file name and extension. + Debug.Assert(!assemblyPath.EndsWith("\\", StringComparison.Ordinal), "the assembly path should be a full file path containing file extension"); + + // LoadFile will only override your request only if it is in the GAC + retassem = Assembly.LoadFile(assemblyPath); + } + // + // At compile time, the build task should always pass the full path of the referenced assembly, even if it + // comes from GAC. But below code snippet can run if parser wants to try loading an assembly w/o a path. + // This also makes run-time assembly load consistent with compile-time semantics. + else + { + try + { + retassem = Assembly.Load(assemblyGivenName); + } + catch (System.IO.FileNotFoundException) + { + // This may be a locally defined assembly that has not been created yet. + // To support these cases, just set a null assembly and return. This + // will fail downstream if it really was an assembly miss. + retassem = null; + } + } + } + + // Cache the assembly + if (retassem != null) + { + _loadedAssembliesHash[assemblyShortName] = retassem; + } + } + + return retassem; + } + + private static Hashtable _loadedAssembliesHash = new Hashtable(8); +#else + // returns true is sourceAssembly declares LocalAssemblyName as a friend + internal static bool IsFriendAssembly(Assembly sourceAssembly) + { + bool isFriend = false; + Type typeValue = null; + + string friendAssemblyName = string.Empty; + IList list = CustomAttributeData.GetCustomAttributes(sourceAssembly); + + for (int j = 0; j < list.Count; j++) + { + friendAssemblyName = GetCustomAttributeData(list[j], typeof(InternalsVisibleToAttribute), out typeValue, false, false, false); + if (friendAssemblyName != null && friendAssemblyName == LocalAssemblyName) + { + isFriend = true; + break; + } + } + + return isFriend; + } + + internal static bool IsInternalAllowedOnType(Type type) + { + return ((LocalAssemblyName == type.Assembly.GetName().Name) || IsFriendAssembly(type.Assembly)); + } + + // The local assembly that contains the baml. + internal static string LocalAssemblyName + { + get { return _localAssemblyName; } + set { _localAssemblyName = value; } + } + + private static string _localAssemblyName = string.Empty; + + internal static bool HasAlreadyReflectionOnlyLoaded(string assemblyNameLookup) + { + // + // If the cache contains an entry for the given assemblyname, and its value is not + // null, it marks the assembly has been loaded. + // + // Since ResetCacheForAssembly( ) just sets "null" in the hashtable for a given assembly + // without really removing it, it is possible that an assembly is not reloaded before this + // method is called. + // Such as for the local-type-ref xaml file compilation, the cache entry for the temporary + // assembly is reset to null, but it is not reloaded for MCPass1. + // + // We don't want to change the behavior of ResetCacheForAssembly( ) at this moment. (Resetting + // the value to null without really removing the entry is helpful for the perf) + // + + return (_reflectionOnlyLoadedAssembliesHash.Contains(assemblyNameLookup) && _reflectionOnlyLoadedAssembliesHash[assemblyNameLookup] != null); + } + + internal static Assembly GetAlreadyReflectionOnlyLoadedAssembly(string assemblyNameLookup) + { + return (Assembly)_reflectionOnlyLoadedAssembliesHash[assemblyNameLookup]; + } + + // + // For a given assembly name and its full path, Reflection-Only load the assembly directly + // from the file in disk or load the file to memory and then create assembly instance from + // memory buffer data. + // + private static Assembly ReflectionOnlyLoadAssembly(string assemblyName, string fullPathToAssembly) + { + Assembly assembly = null; + + // If the assembly path is empty, try to load assembly by name. LoadFromAssemblyName + // will result in a TypeLoader.Resolve event that will contain more information about the + // requested assembly. + if (String.IsNullOrEmpty(fullPathToAssembly)) + { + return _typeLoader.LoadFromAssemblyName(assemblyName); + } + else if (_cachedTypeLoaderAssemblies.TryGetValue(fullPathToAssembly, out assembly)) + { + return assembly; + } + else if (!String.IsNullOrEmpty(assemblyName) && _cachedTypeLoaderAssemblies.TryGetValue(assemblyName, out assembly)) + { + return assembly; + } + else + { + assembly = _typeLoader.LoadFromAssemblyPath(fullPathToAssembly); + } + + // Add the assembly to the cache. ReflectionHelper.ReflectionOnlyLoadAssembly + // receives frequent calls requesting the same assembly. + if (assembly != null && fullPathToAssembly != null) + { + _cachedTypeLoaderAssemblies.Add(fullPathToAssembly, assembly); + _cachedTypeLoaderReferencePaths.Add(Path.GetDirectoryName(fullPathToAssembly)); + } + + return assembly; + } + + // Handler for TypeLoader.Resolving event responsible for assembly probing and loading. + // TypeLoader will fire the Resolving event when an assembly or a dependent assembly is + // required in response to a reflection request. Probing strategy that will + // find all dependent DLLs, even those in other NuGet packages, must be implemented + // here. The probing responsibility up to the consumer of System.Reflection.TypeLoader. + private static System.Reflection.Assembly TypeLoaderResolvingHandler( + System.Reflection.TypeLoader typeLoader, System.Reflection.AssemblyName assemblyName) + { + // Resolve is called at most once per assembly. + foreach (var path in _cachedTypeLoaderReferencePaths) + { + string fullFilePath = path + "\\" + assemblyName.Name + ".dll"; + + if (System.IO.File.Exists(fullFilePath)) + { + // TODO: PBT Porting: Temporarily relax this restriction for testing. + // Do not require a specific version, culture, or public key token + // of the assembly. Update this block when testing is complete. + return _typeLoader.LoadFromStream(File.OpenRead(fullFilePath)); + } + } + + return null; + } + + private static Hashtable _reflectionOnlyLoadedAssembliesHash = new Hashtable(8); + + // + // Copy assembly file from disk to memory, and return the memory buffer. + // + internal static byte[] GetAssemblyContent(string filepath) + { + byte[] asmContents = null; + + using (FileStream fileStream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + // FileStream.Read does not support offsets or lengths + // larger than int.MaxValue. + if (fileStream.Length > int.MaxValue) + { + return null; + } + + int size = (int)fileStream.Length; + asmContents = new byte[size]; + if (size > 0) + { + ReliableRead(fileStream, asmContents, 0, size); + } + + // With using statement, fileStream can always be disposed, + // there is no need to put code here to explicitly dispose the + // file stream object. + } + + return asmContents; + } + + // + // set flag for the assembly to indicate that this assembly should be loaded from memory buffer + // instead of file in disk. + // + // Usually it is called by MarkupCompiler task. + // + internal static void SetContentLoadForAssembly(string assemblyName) + { + string assemblyNameLookup = assemblyName.ToUpper(CultureInfo.InvariantCulture); + _contentLoadAssembliesHash[assemblyNameLookup] = true; + } + + /// + /// Read utility that is guaranteed to return the number of bytes requested + /// if they are available. + /// + /// stream to read from + /// buffer to read into + /// offset in buffer to write to + /// bytes to read + /// bytes read + /// Normal Stream.Read does not guarantee how many bytes it will + /// return. This one does. + private static int ReliableRead(Stream stream, byte[] buffer, int offset, int count) + { + /* Invariant.Assert is not available in PBT + Invariant.Assert(stream != null); + Invariant.Assert(buffer != null); + Invariant.Assert(buffer.Length > 0); + Invariant.Assert(offset >= 0); + Invariant.Assert(count >= 0); + Invariant.Assert(checked(offset + count<= buffer.Length)); + */ + + // let's read the whole block into our buffer + int totalBytesRead = 0; + while (totalBytesRead < count) + { + int bytesRead = stream.Read(buffer, + offset + totalBytesRead, + count - totalBytesRead); + if (bytesRead == 0) + { + break; + } + totalBytesRead += bytesRead; + } + return totalBytesRead; + } + + private static Hashtable _contentLoadAssembliesHash = new Hashtable(1); +#endif + + #endregion Assembly Loading + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/Replacements/TypeUriConverter.cs b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/Replacements/TypeUriConverter.cs new file mode 100644 index 00000000000..7dde5021f1c --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/Replacements/TypeUriConverter.cs @@ -0,0 +1,133 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// +// +// Contents: Limited converter for string <--> System.Uri +// +// + +namespace System.Xaml.Replacements +{ + using System; + using System.ComponentModel; + using System.ComponentModel.Design.Serialization; + using System.Globalization; + using System.Reflection; + + internal class TypeUriConverter : TypeConverter + { + public TypeUriConverter() + { + } + + /// + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == null) + { + throw new ArgumentNullException(nameof(sourceType)); + } + + return sourceType == typeof(string) || sourceType == typeof(Uri); + } + + /// + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + return + destinationType == typeof(InstanceDescriptor) || + destinationType == typeof(string) || + destinationType == typeof(Uri); + } + + /// + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + var uri = value as Uri; + if (uri != null) + { + var uriKind = UriKind.RelativeOrAbsolute; + if (uri.IsWellFormedOriginalString()) + { + uriKind = uri.IsAbsoluteUri ? UriKind.Absolute : UriKind.Relative; + } + + if (destinationType == typeof(InstanceDescriptor)) + { + var ci = + typeof(Uri) + .GetConstructor( + BindingFlags.Public | BindingFlags.Instance, + null, + new Type[] { typeof(string), typeof(UriKind) }, + null); + return + new InstanceDescriptor( + ci, + new object[] { uri.OriginalString, uriKind}); + } + + if (destinationType == typeof(string)) + { + return uri.OriginalString; + } + + if (destinationType == typeof(Uri)) + { + return new Uri(uri.OriginalString, uriKind); + } + } + + return base.ConvertTo(context, culture, value, destinationType); + } + + /// + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + var uriString = value as string; + if (uriString != null) + { + if (Uri.IsWellFormedUriString(uriString, UriKind.Absolute)) + { + return new Uri(uriString, UriKind.Absolute); + } + + if (Uri.IsWellFormedUriString(uriString, UriKind.Relative)) + { + return new Uri(uriString, UriKind.Relative); + } + + return new Uri(uriString, UriKind.RelativeOrAbsolute); + } + + var uri = value as Uri; + if (uri != null) + { + if (uri.IsWellFormedOriginalString()) + { + return new Uri(uri.OriginalString, uri.IsAbsoluteUri ? UriKind.Absolute : UriKind.Relative); + } + + return new Uri(uri.OriginalString, UriKind.RelativeOrAbsolute); + } + + return base.ConvertFrom(context, culture, value); + } + + /// + public override bool IsValid(ITypeDescriptorContext context, object value) + { + var uriString = value as string; + if (uriString != null) + { + Uri result = null; + return Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out result); + } + + return value is Uri; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/RuntimeIdentifierPropertyAttribute.cs b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/RuntimeIdentifierPropertyAttribute.cs new file mode 100644 index 00000000000..9303d367a95 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/RuntimeIdentifierPropertyAttribute.cs @@ -0,0 +1,135 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Description: +// This attribute is placed on a class to identify the property that will +// function as an Name for the given class + +using System; +using System.Globalization; +using SRCS = System.Runtime.CompilerServices; + +#if PBTCOMPILER +namespace MS.Internal.Markup +#elif WINDOWS_BASE +using MS.Internal.WindowsBase; // FriendAccessAllowed +namespace System.Windows.Markup +#else +namespace System.Windows.Markup +#endif +{ +#if !PBTCOMPILER && !TARGETTING35SP1 && !WINDOWS_BASE + /// + /// This attribute is placed on a class to identify the property that will + /// function as an Name for the given class + /// + [AttributeUsage(AttributeTargets.Class)] + [SRCS.TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class RuntimeNamePropertyAttribute: Attribute + { + /// + public RuntimeNamePropertyAttribute(string name) + { + _name = name; + } + + /// + /// The Name of the property in the class that will contain the ID of + /// the class, this property needs to be of type string and have + /// both get and set access + /// + public string Name + { + get + { + return _name; + } + } + + private string _name = null; + } +#endif + +#if !SYSTEM_XAML + /// + /// The string used in RuntimeNameProperty is expected to follow certain + /// rules. IsValidIdentifierName checks the given string against the rules. + /// NameValidationCallback extends to all object types and is in the right + /// format to be used as a DependencyProperty ValidateValueCallback + /// + internal static class NameValidationHelper + { + // When a name string comes in programatically, validate it against the + // same rules used by the XAML parser. In XAML scenarios this is + // technically redundant since the parser has already checked it against + // the same rules, but the parser is able to give a better error message + // when it happens. +#if !PBTCOMPILER + [FriendAccessAllowed] // Built into Base, used by Core and Framework. + internal static bool NameValidationCallback(object candidateName) + { + string name = candidateName as string; + + if( name != null ) + { + // Non-null string, ask the XAML validation code for blessing. + return IsValidIdentifierName(name); + } + else if( candidateName == null ) + { + // Null string is allowed + return true; + } + else + { + // candiateName is not a string object. + return false; + } + } +#endif + + /// + /// Validates the name to follow Naming guidelines + /// + /// string to validate +#if !PBTCOMPILER + [FriendAccessAllowed] // Built into Base, used by Core and Framework. +#endif + internal static bool IsValidIdentifierName(string name) + { + // Grammar: + // ::= ( | )* + // ::= [{Lu}{Ll}{Lt}{Lo}{Nl}('_')] + // ::= [{Mn}{Mc}{Lm}{Nd}] + UnicodeCategory uc; + for (int i = 0; i < name.Length; i++) + { + uc = Char.GetUnicodeCategory(name[i]); + bool idStart = (uc == UnicodeCategory.UppercaseLetter || // (Lu) + uc == UnicodeCategory.LowercaseLetter || // (Ll) + uc == UnicodeCategory.TitlecaseLetter || // (Lt) + uc == UnicodeCategory.OtherLetter || // (Lo) + uc == UnicodeCategory.LetterNumber || // (Nl) + name[i] == '_'); + bool idExtend = (uc == UnicodeCategory.NonSpacingMark || // (Mn) + uc == UnicodeCategory.SpacingCombiningMark || // (Mc) + uc == UnicodeCategory.ModifierLetter || // (Lm) + uc == UnicodeCategory.DecimalDigitNumber); // (Nd) + if (i == 0) + { + if (!idStart) + { + return false; + } + } + else if (!(idStart || idExtend)) + { + return false; + } + } + return true; + } + } +#endif +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/TypeConverterHelper.cs b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/TypeConverterHelper.cs new file mode 100644 index 00000000000..76a9dad599f --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/TypeConverterHelper.cs @@ -0,0 +1,496 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Description: Specifies that the whitespace surrounding an element should be trimmed. +// + +using System; +using System.Reflection; +using System.ComponentModel; +using System.Globalization; +using System.Diagnostics; +#if SYSTEM_XAML +using System.Xaml.Replacements; +#endif + +#if PBTCOMPILER +namespace MS.Internal.Markup +#elif SYSTEM_XAML +namespace System.Xaml +#else +namespace System.Windows.Markup +#endif +{ + + /// + /// Class that provides fucntionality to obtain a TypeConverter from a property or the + /// type of the property, based on logic similar to TypeDescriptor.GetConverter. + /// + internal static class TypeConverterHelper + { + private static CultureInfo invariantEnglishUS = CultureInfo.InvariantCulture; + + internal static CultureInfo InvariantEnglishUS + { + get + { + return invariantEnglishUS; + } + } + +#if !SYSTEM_XAML + internal static MemberInfo GetMemberInfoForPropertyConverter(object dpOrPiOrMi) + { + MemberInfo memberInfo = dpOrPiOrMi as PropertyInfo; + + if (memberInfo == null) + { + MethodInfo methodInfo; +#if !PBTCOMPILER + DependencyProperty dp = dpOrPiOrMi as DependencyProperty; + + if (dp != null) + { + // While parsing styles or templates, we end up getting a DependencyProperty, + // even for non-attached cases. In this case, we try fetching the CLR + // property info and getting its attributes. + memberInfo = dp.OwnerType.GetProperty( + dp.Name, + BindingFlags.Instance | BindingFlags.Public | + BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); + + // We failed to get a CLR wrapper for the DependencyProperty, so we + // assume that this is an attached property and look for the MethodInfo + // for the static getter. + if (memberInfo == null) + { + // Get the method member that defines the DependencyProperty + memberInfo = dp.OwnerType.GetMethod( + "Get" + dp.Name, + BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.Static | BindingFlags.FlattenHierarchy); + } + } + else +#endif + if ((methodInfo = dpOrPiOrMi as MethodInfo) != null) + { + // miSetter may not be a MethodInfo when we are dealing with event handlers that + // belong to local assemblies. One such case is encountered when building DrtCompiler. + if (methodInfo.GetParameters().Length == 1) + { + // Use Getter of the attached property + memberInfo = methodInfo; + } + else + { + // Use the Setter of the attached property (if any) + memberInfo = methodInfo.DeclaringType.GetMethod( + "Get" + methodInfo.Name.Substring("Set".Length), + BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.Static | BindingFlags.FlattenHierarchy); + } + } + } + + return memberInfo; + } + + internal static Type GetConverterType(MemberInfo memberInfo) + { + Debug.Assert(null != memberInfo, "Null passed for memberInfo to GetConverterType"); + + Type converterType = null; + + // Try looking for the TypeConverter for the type using reflection. + string converterName = ReflectionHelper.GetTypeConverterAttributeData(memberInfo, out converterType); + + if (converterType == null) + { + converterType = GetConverterTypeFromName(converterName); + } + + return converterType; + } +#endif + internal static Type GetConverterType(Type type) + { + Debug.Assert(null != type, "Null passed for type to GetConverterType"); + + Type converterType = null; + + // Try looking for the TypeConverter for the type using reflection. + string converterName = ReflectionHelper.GetTypeConverterAttributeData(type, out converterType); + + if (converterType == null) + { + converterType = GetConverterTypeFromName(converterName); + } + + return converterType; + } + + private static Type GetConverterTypeFromName(string converterName) + { + Type converterType = null; + + if (!string.IsNullOrEmpty(converterName)) + { + converterType = ReflectionHelper.GetQualifiedType(converterName); + + if (converterType != null) + { + // Validate that this is an accessible type converter. + if (!ReflectionHelper.IsPublicType(converterType)) + { +#if PBTCOMPILER + if (!ReflectionHelper.IsInternalType(converterType) || + !ReflectionHelper.IsInternalAllowedOnType(converterType)) + { +#endif + converterType = null; +#if PBTCOMPILER + } +#endif + } + } + } + + return converterType; + } +#if !SYSTEM_XAML + internal static Type GetCoreConverterTypeFromCustomType(Type type) + { + Type converterType = null; + if (type.IsEnum) + { + // Need to handle Enums types specially as they require a ctor that + // takes the underlying type, but at compile time we only need to know + // the Type of the Converter and not an actual instance of it. + converterType = typeof(EnumConverter); + } + else if (typeof(Int32).IsAssignableFrom(type)) + { + converterType = typeof(Int32Converter); + } + else if (typeof(Int16).IsAssignableFrom(type)) + { + converterType = typeof(Int16Converter); + } + else if (typeof(Int64).IsAssignableFrom(type)) + { + converterType = typeof(Int64Converter); + } + else if (typeof(UInt32).IsAssignableFrom(type)) + { + converterType = typeof(UInt32Converter); + } + else if (typeof(UInt16).IsAssignableFrom(type)) + { + converterType = typeof(UInt16Converter); + } + else if (typeof(UInt64).IsAssignableFrom(type)) + { + converterType = typeof(UInt64Converter); + } + else if (typeof(Boolean).IsAssignableFrom(type)) + { + converterType = typeof(BooleanConverter); + } + else if (typeof(Double).IsAssignableFrom(type)) + { + converterType = typeof(DoubleConverter); + } + else if (typeof(Single).IsAssignableFrom(type)) + { + converterType = typeof(SingleConverter); + } + else if (typeof(Byte).IsAssignableFrom(type)) + { + converterType = typeof(ByteConverter); + } + else if (typeof(SByte).IsAssignableFrom(type)) + { + converterType = typeof(SByteConverter); + } + else if (typeof(Char).IsAssignableFrom(type)) + { + converterType = typeof(CharConverter); + } + else if (typeof(Decimal).IsAssignableFrom(type)) + { + converterType = typeof(DecimalConverter); + } + else if (typeof(TimeSpan).IsAssignableFrom(type)) + { + converterType = typeof(TimeSpanConverter); + } + else if (typeof(Guid).IsAssignableFrom(type)) + { + converterType = typeof(GuidConverter); + } + else if (typeof(String).IsAssignableFrom(type)) + { + converterType = typeof(StringConverter); + } + else if (typeof(CultureInfo).IsAssignableFrom(type)) + { + converterType = typeof(CultureInfoConverter); + } + else if (typeof(Type).IsAssignableFrom(type)) + { + converterType = typeof(TypeTypeConverter); + } + else if (typeof(DateTime).IsAssignableFrom(type)) + { + converterType = typeof(DateTimeConverter2); + } + + return converterType; + } +#endif +#if !PBTCOMPILER + private static TypeConverter GetCoreConverterFromCoreType(Type type) + { + TypeConverter typeConverter = null; + if (type == typeof(Int32)) + { + typeConverter = new System.ComponentModel.Int32Converter(); + } + else if (type == typeof(Int16)) + { + typeConverter = new System.ComponentModel.Int16Converter(); + } + else if (type == typeof(Int64)) + { + typeConverter = new System.ComponentModel.Int64Converter(); + } + else if (type == typeof(UInt32)) + { + typeConverter = new System.ComponentModel.UInt32Converter(); + } + else if (type == typeof(UInt16)) + { + typeConverter = new System.ComponentModel.UInt16Converter(); + } + else if (type == typeof(UInt64)) + { + typeConverter = new System.ComponentModel.UInt64Converter(); + } + else if (type == typeof(Boolean)) + { + typeConverter = new System.ComponentModel.BooleanConverter(); + } + else if (type == typeof(Double)) + { + typeConverter = new System.ComponentModel.DoubleConverter(); + } + else if (type == typeof(Single)) + { + typeConverter = new System.ComponentModel.SingleConverter(); + } + else if (type == typeof(Byte)) + { + typeConverter = new System.ComponentModel.ByteConverter(); + } + else if (type == typeof(SByte)) + { + typeConverter = new System.ComponentModel.SByteConverter(); + } + else if (type == typeof(Char)) + { + typeConverter = new System.ComponentModel.CharConverter(); + } + else if (type == typeof(Decimal)) + { + typeConverter = new System.ComponentModel.DecimalConverter(); + } + else if (type == typeof(TimeSpan)) + { + typeConverter = new System.ComponentModel.TimeSpanConverter(); + } + else if (type == typeof(Guid)) + { + typeConverter = new System.ComponentModel.GuidConverter(); + } + else if (type == typeof(String)) + { + typeConverter = new System.ComponentModel.StringConverter(); + } + else if (type == typeof(CultureInfo)) + { + typeConverter = new System.ComponentModel.CultureInfoConverter(); + } +#if !SYSTEM_XAML + else if (type == typeof(Type)) + { + typeConverter = new System.Windows.Markup.TypeTypeConverter(); + } +#else + else if (type == typeof(Type)) + { + typeConverter = new System.Xaml.Replacements.TypeTypeConverter(); + } +#endif + else if (type == typeof(DateTime)) + { + typeConverter = new DateTimeConverter2(); + } + else if (ReflectionHelper.IsNullableType(type)) + { + typeConverter = new System.ComponentModel.NullableConverter(type); + } + + return typeConverter; + } + + internal static TypeConverter GetCoreConverterFromCustomType(Type type) + { + TypeConverter typeConverter = null; + if (type.IsEnum) + { + // Need to handle Enums types specially as they require a ctor that + // takes the underlying type. + typeConverter = new System.ComponentModel.EnumConverter(type); + } + else if (typeof(Int32).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.Int32Converter(); + } + else if (typeof(Int16).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.Int16Converter(); + } + else if (typeof(Int64).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.Int64Converter(); + } + else if (typeof(UInt32).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.UInt32Converter(); + } + else if (typeof(UInt16).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.UInt16Converter(); + } + else if (typeof(UInt64).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.UInt64Converter(); + } + else if (typeof(Boolean).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.BooleanConverter(); + } + else if (typeof(Double).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.DoubleConverter(); + } + else if (typeof(Single).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.SingleConverter(); + } + else if (typeof(Byte).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.ByteConverter(); + } + else if (typeof(SByte).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.SByteConverter(); + } + else if (typeof(Char).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.CharConverter(); + } + else if (typeof(Decimal).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.DecimalConverter(); + } + else if (typeof(TimeSpan).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.TimeSpanConverter(); + } + else if (typeof(Guid).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.GuidConverter(); + } + else if (typeof(String).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.StringConverter(); + } + else if (typeof(CultureInfo).IsAssignableFrom(type)) + { + typeConverter = new System.ComponentModel.CultureInfoConverter(); + } +#if !SYSTEM_XAML + else if (typeof(Type).IsAssignableFrom(type)) + { + typeConverter = new System.Windows.Markup.TypeTypeConverter(); + } +#else + else if (type == typeof(Type)) + { + typeConverter = new System.Xaml.Replacements.TypeTypeConverter(); + } +#endif + else if (typeof(DateTime).IsAssignableFrom(type)) + { + typeConverter = new DateTimeConverter2(); + } + else if (typeof(Uri).IsAssignableFrom(type)) + { + typeConverter = new System.Xaml.Replacements.TypeUriConverter(); + } + + return typeConverter; + } + + /// + /// Returns a TypeConverter for the given target Type, otherwise null if not found. + /// First, if the type is one of the known system types, it lookups a table to determine the TypeConverter. + /// Next, it tries to find a TypeConverterAttribute on the type using reflection. + /// Finally, it looks up the table of known typeConverters again if the given type derives from one of the + /// known system types. + /// + /// The target Type for which to find a TypeConverter. + /// A TypeConverter for the Type type if found. Null otherwise. + internal static TypeConverter GetTypeConverter(Type type) + { + if (type == null) + { + throw new ArgumentNullException("type"); + } + + TypeConverter typeConverter = GetCoreConverterFromCoreType(type); + + if (typeConverter == null) + { + Type converterType = GetConverterType(type); + if (converterType != null) + { + typeConverter = Activator.CreateInstance(converterType, + BindingFlags.Instance | BindingFlags.CreateInstance | BindingFlags.Public, + null, + null, + InvariantEnglishUS) as TypeConverter; + } + else + { + typeConverter = GetCoreConverterFromCustomType(type); + } + + if (typeConverter == null) + { + typeConverter = new TypeConverter(); + } + } + + return typeConverter; + } +#endif + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/XmlCompatibilityReader.cs b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/XmlCompatibilityReader.cs new file mode 100644 index 00000000000..534f0d693e4 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/XmlCompatibilityReader.cs @@ -0,0 +1,2065 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Xml; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Diagnostics; +using System.Threading; + +#if SYSTEM_XAML +using System.Xaml; +#endif + +#if PBTCOMPILER +using MS.Utility; +namespace MS.Internal.Markup +#elif SYSTEM_XAML +using System.Windows; + +namespace System.Xaml +#else +using MS.Internal.WindowsBase; +using System.Windows; + +namespace System.Windows.Markup +#endif +{ +#if !PBTCOMPILER && !SYSTEM_XAML + [FriendAccessAllowed] +#endif + + // + // true if xmlNamespace is recognized + // + // + // the namespace to be checked + // + // + // if the passed in namespace is subsumed, then newXmlNamespace returns the subsuming namespace. + // + internal delegate bool IsXmlNamespaceSupportedCallback(string xmlNamespace, out string newXmlNamespace); + delegate void HandleElementCallback(int elementDepth, ref bool more); + delegate void HandleAttributeCallback(int elementDepth); +#if !PBTCOMPILER && !SYSTEM_XAML + [FriendAccessAllowed] +#endif + internal sealed class XmlCompatibilityReader : XmlWrappingReader + { + #region Construction + public XmlCompatibilityReader(XmlReader baseReader) + : base(baseReader) + { + _compatibilityScope = new CompatibilityScope(null, -1, this); + + foreach (string xmlNamespace in _predefinedNamespaces) + { + AddKnownNamespace(xmlNamespace); + _namespaceMap[xmlNamespace] = xmlNamespace; + Reader.NameTable.Add(xmlNamespace); + } + + _elementHandler.Add(AlternateContent, new HandleElementCallback(HandleAlternateContent)); + _elementHandler.Add(Choice, new HandleElementCallback(HandleChoice)); + _elementHandler.Add(Fallback, new HandleElementCallback(HandleFallback)); + + _attributeHandler.Add(Ignorable, new HandleAttributeCallback(HandleIgnorable)); + _attributeHandler.Add(MustUnderstand, new HandleAttributeCallback(HandleMustUnderstand)); + _attributeHandler.Add(ProcessContent, new HandleAttributeCallback(HandleProcessContent)); + _attributeHandler.Add(PreserveElements, new HandleAttributeCallback(HandlePreserveElements)); + _attributeHandler.Add(PreserveAttributes, new HandleAttributeCallback(HandlePreserveAttributes)); + } + + public XmlCompatibilityReader(XmlReader baseReader, + IsXmlNamespaceSupportedCallback isXmlNamespaceSupported) + : this(baseReader) + { + _namespaceCallback = isXmlNamespaceSupported; + } + + public XmlCompatibilityReader(XmlReader baseReader, + IsXmlNamespaceSupportedCallback isXmlNamespaceSupported, + IEnumerable supportedNamespaces) + : this(baseReader, isXmlNamespaceSupported) + { + foreach (string xmlNamespace in supportedNamespaces) + { + AddKnownNamespace(xmlNamespace); + _namespaceMap[xmlNamespace] = xmlNamespace; + } + } + +#if !PBTCOMPILER + public XmlCompatibilityReader(XmlReader baseReader, + IEnumerable supportedNamespaces) + : this(baseReader, null, supportedNamespaces) + { + } +#endif + #endregion Construction + + #region Public Methods + /// + /// replaces all future references of namespace URI 'oldNamespace' with 'newNamespace' + /// + /// + /// the namespace to subsume with + /// + /// + /// the namespace to be subsumed + /// + public void DeclareNamespaceCompatibility(string newNamespace, string oldNamespace) + { + if (newNamespace != oldNamespace) + { + // indicate that newNamespace subsumes another namespace + AddSubsumingNamespace(newNamespace); + + // If newNamespace is mapped to a namespace, + string tempNamespace; + if (_namespaceMap.TryGetValue(newNamespace, out tempNamespace)) + { + // If we have mapped newNamespace already get the newest name. + // We don't have to do this recursively because of the code below + // ensures the map always refers to the newest namespace. + newNamespace = tempNamespace; + } + + if (IsSubsumingNamespace(oldNamespace)) + { + // if we are mapping what was used as a new namespace to a newer name, + // scan the _newNamespaces dictionary and update the entries. We collect + // a list to avoid updating the dictonary during enumeration. + List keysToUpdate = new List(); + + foreach (KeyValuePair pair in _namespaceMap) + { + if (pair.Value == oldNamespace) + { + keysToUpdate.Add(pair.Key); + } + } + + foreach (string key in keysToUpdate) + { + _namespaceMap[key] = newNamespace; + } + } + } + + _namespaceMap[oldNamespace] = newNamespace; + } + + /// + /// Reads the next node from the stream. + /// + /// + /// true if the next node was read successfully; false if there are no more nodes to read. + /// + public override bool Read() + { + // Previous element was an empty element. So if we pushed a scope, then get rid of the scope first. + if (isPreviousElementEmpty) + { + isPreviousElementEmpty = false; + ScanForEndCompatibility(previousElementDepth); + } + + bool more = Reader.Read(); //passed as ref arg to ReadStartElement and ReadEndElement + bool result = false; + + while (more) + { + switch (Reader.NodeType) + { + case XmlNodeType.Element: + { + // if the element read should be ignored, read the next element + if (!ReadStartElement(ref more)) + { + continue; + } + break; + } + case XmlNodeType.EndElement: + { + // if the element read should be ignored, read the next element + if (!ReadEndElement(ref more)) + { + continue; + } + break; + } + } + + // if the element was read successfully and was not ignored, break and return true + result = true; + break; + } + + return result; + } + + /// + /// Used to handle 'start element' tags. These are actually + /// just called 'element' tags, the 'start' is just for clarity + /// + /// + /// is set to true if there is the document contains more elements, false if the end of the + /// document has been reached. + /// + /// + /// true if an element was read that should not be ignored + /// false if the element read should be ignored or the end of document has been reached + /// + private bool ReadStartElement(ref bool more) + { + // when processing elements, the Reader may advance to another element or attribute, + // so we save the values of the current element here + int elementDepth = Reader.Depth; + int depthOffset = _depthOffset; + bool isEmpty = Reader.IsEmptyElement; + string namespaceName = NamespaceURI; + bool result = false; + + if (object.ReferenceEquals(namespaceName, CompatibilityUri)) + { + // if the element is a markup-compatibility element, we get the appropriate handler for + // the element type, and call the appropriate delegate. If the element is not recognized + // we throw an exception. + string elementName = Reader.LocalName; + HandleElementCallback elementCB; + if (!_elementHandler.TryGetValue(elementName, out elementCB)) + { + Error(SR.Get(SRID.XCRUnknownCompatElement), elementName); + } + elementCB(elementDepth, ref more); + } + // handle non-markup-compatibility elements + else + { + // check for markup-compatibility attributes and namespaces that should be ignored + ScanForCompatibility(elementDepth); + + if (ShouldIgnoreNamespace(namespaceName)) + { + if (Scope.ShouldProcessContent(namespaceName, Reader.LocalName)) + { + // if the current element is unknown and has been marked Ignorable and ProcessContent, + // then read the next element, and increase depth offset + if (Scope.Depth == elementDepth) + { + // if the current element pushed a scope, mark the scope as InProcessContent to + // note that for certain logic this scope's parent should be checked + Scope.InProcessContent = true; + } + _depthOffset++; + more = Reader.Read(); + } + else + { + // if element should be ignored but not processed, check to see if scope must be popped, + // then skip to the next element after the end tag of the current element + ScanForEndCompatibility(elementDepth); + Reader.Skip(); + } + } + else + { + if (Scope.InAlternateContent) + { + // if this element is the child of an AlternateContent element, then throw an exception. + Error(SR.Get(SRID.XCRInvalidACChild), Reader.Name); + } + + result = true; + } + } + + // if the element is empty (e.g. "" and we pushed a scope then we need to set a flag + // to get rid of the scope when we hit the next element. + // We also need to store the current elementDepth. + if (isEmpty) + { + isPreviousElementEmpty = true; + previousElementDepth = elementDepth; + _depthOffset = depthOffset; + } + + return result; + } + + /// + /// Used to handle any end element tag + /// + /// + /// is set to true if there is the document contains more elements, false if the end of the + /// document has been reached. + /// + /// + /// true if an element was read that should not be ignored + /// false if the element read should be ignored or the end of document has been reached + /// + private bool ReadEndElement(ref bool more) + { + // when reading attributes, the reader's depth increases, so for consistency + // we store the depth before reading any attributes + int elementDepth = Reader.Depth; + string namespaceName = NamespaceURI; + bool result = false; // return value + + if (object.ReferenceEquals(namespaceName, CompatibilityUri)) + { + // if the element is a markup-compatibility element, pop a scope, decrement the + // depth offset and read the next element. + string elementName = Reader.LocalName; + if (object.ReferenceEquals(elementName, AlternateContent)) + { + if (!Scope.ChoiceSeen) + { + // if the current element was a , without any Choice + // element children, throw an exception + Error(SR.Get(SRID.XCRChoiceNotFound)); + } + } + _depthOffset--; + PopScope(); //we know we can pop, so no need to scan + more = Reader.Read(); + } + else + { + if (ShouldIgnoreNamespace(namespaceName)) + { + // if current element is Ignorable, then to be on it, it must have been marked + // ProcessContent. Pop a scope if the corresponding start element pushed a scope a + // scope, decrement the depth offset and read the next element. + Debug.Assert(Scope.ShouldProcessContent(namespaceName, Reader.LocalName)); + ScanForEndCompatibility(elementDepth); + _depthOffset--; + more = Reader.Read(); + } + else + { + ScanForEndCompatibility(elementDepth); + result = true; + } + } + + return result; + } + + /// + /// Gets the value of the attribute with the specified index. + /// + /// + /// The index of the attribute. The index is zero-based. (The first attribute has index 0.) + /// + /// + /// The value of the specified attribute. If the attribute is not found, a null reference is returned. + /// + public override string GetAttribute(int i) + { + string result = null; + + if (_ignoredAttributeCount == 0) + { + // if the current element should not ignored any of its attributes, skip extra logic + result = Reader.GetAttribute(i); + } + else + { + SaveReaderPosition(); + + // move to 'i'th attribute, get its value + MoveToAttribute(i); + result = Reader.Value; + + RestoreReaderPosition(); + } + + return result; + } + + /// + /// Gets the value of the attribute with the specified name. + /// + /// + /// The qualified name of the attribute. + /// + /// + /// The value of the specified attribute. If the attribute is not found, a null reference is returned. + /// + public override string GetAttribute(string name) + { + string result = null; + + if (_ignoredAttributeCount == 0) + { + // if the current element should not ignored any attributes, call Reader method + result = Reader.GetAttribute(name); + } + else + { + SaveReaderPosition(); + + // move to "name" attribute + if (MoveToAttribute(name)) + { + result = Reader.Value; + RestoreReaderPosition(); + } + } + + return result; + } + + /// + /// Gets the value of the attribute with the specified local name and namespace URI. + /// + /// + /// The local name of the attribute. + /// + /// + /// The namespace URI of the attribute. + /// + /// + /// The value of the specified attribute. If the attribute is not found, a null reference is returned. + /// + public override string GetAttribute(string localName, string namespaceURI) + { + string result = null; + + if (_ignoredAttributeCount == 0 || !ShouldIgnoreNamespace(namespaceURI)) + { + // if the current element does not have any attributes that should be ignored or + // the namespace provided is not ignorable, call Reader method + result = Reader.GetAttribute(localName, namespaceURI); + } + + return result; + } + + /// + /// Gets the value of the attribute with the specified index. + /// + /// + /// The index of the attribute. The index is zero-based. (The first attribute has index 0.) + /// + /// + /// true if the attribute is found; otherwise, false. If false, the reader's position does not change. + /// + public override void MoveToAttribute(int i) + { + if (_ignoredAttributeCount == 0) + { + // if the current element should not ignored any attributes, call Reader method + Reader.MoveToAttribute(i); + } + else if (i < 0 || i >= AttributeCount) + { + throw new ArgumentOutOfRangeException("i"); + } + else + { + // move Reader to first attribute and iterate until 'i'th element found + Reader.MoveToFirstAttribute(); + + while (true) + { + if (!ShouldIgnoreNamespace(NamespaceURI)) + { + // if attribute should not be ignored, decrement 'i', if i == 0 we've found element + if (i-- == 0) + { + break; + } + } + + Reader.MoveToNextAttribute(); + } + } + } + + /// + /// Moves to the attribute with the specified name. + /// + /// + /// The qualified name of the attribute. + /// + /// + /// true if the attribute is found; otherwise, false. If false, the reader's position does not change. + /// + public override bool MoveToAttribute(string name) + { + bool result; + + if (_ignoredAttributeCount == 0) + { + // if the current element should not ignored any attributes, call Reader method + result = Reader.MoveToAttribute(name); + } + else + { + SaveReaderPosition(); + + result = Reader.MoveToAttribute(name); + if (result && ShouldIgnoreNamespace(NamespaceURI)) + { + // if attribute should be ignored, return false and restore state + result = false; + RestoreReaderPosition(); + } + } + + return result; + } + + /// + /// Moves to the attribute with the specified local name and namespace URI. + /// + /// + /// The local name of the attribute. + /// + /// + /// The namespace URI of the attribute. + /// + /// + /// true if the attribute is found; otherwise, false. If false, the reader's position does not change. + /// + public override bool MoveToAttribute(string localName, string namespaceURI) + { + bool result; + + if (_ignoredAttributeCount == 0) + { + // if the current element should not ignored any attributes, call Reader method + result = Reader.MoveToAttribute(localName, namespaceURI); + } + else + { + SaveReaderPosition(); + + result = Reader.MoveToAttribute(localName, namespaceURI); + + if (result && ShouldIgnoreNamespace(namespaceURI)) + { + result = false; + RestoreReaderPosition(); + } + } + return result; + } + + /// + /// Moves to the first attribute. + /// + /// + /// true if an attribute exists (the reader moves to the first attribute); + /// otherwise, false (the position of the reader does not change). + /// + public override bool MoveToFirstAttribute() + { + bool result = HasAttributes; + + if (result) + { + MoveToAttribute(0); + } + + return result; + } + + /// + /// Moves to the next attribute. + /// + /// + /// true if there is a next attribute; false if there are no more attributes. + /// + public override bool MoveToNextAttribute() + { + bool result; + + if (_ignoredAttributeCount == 0) + { + // if the current element should not ignored any attributes, call Reader method + result = Reader.MoveToNextAttribute(); + } + else + { + SaveReaderPosition(); + + result = Reader.MoveToNextAttribute(); + + if (result) + { + result = SkipToKnownAttribute(); + + if (!result) + { + // if no more attributes exist that should not be ignored, return false and restore state + RestoreReaderPosition(); + } + } + } + + return result; + } + + /// + /// Resolves a namespace prefix in the current element's scope. + /// + /// + /// The prefix whose namespace URI you want to resolve. To match the default namespace, + /// pass an empty string. This string does not have to be atomized. + /// + /// + /// The namespace URI to which the prefix maps or a null reference if no matching prefix is found. + /// + public override string LookupNamespace(string prefix) + { + string namespaceName = Reader.LookupNamespace(prefix); + + if (namespaceName != null) + { + namespaceName = GetMappedNamespace(namespaceName); + } + + return namespaceName; + } + + #endregion Public Methods + + #region Public Properties + + /// + /// This override is to ensure that the value + /// for the xmlns attribute reflects all the + /// compatibility (subsuming) rules. + /// + public override string Value + { + get + { + // Look for xmlns + if (String.Equals(XmlnsDeclaration, Reader.LocalName, StringComparison.Ordinal)) + { + return LookupNamespace(String.Empty); + } + // Look for xmlns: ... + else if (String.Equals(XmlnsDeclaration, Reader.Prefix, StringComparison.Ordinal)) + { + return LookupNamespace(Reader.LocalName); + } + + return Reader.Value; + } + } + + /// + /// Gets the namespace URI (as defined in the W3C Namespace specification) of the node + /// on which the reader is positioned. + /// + public override string NamespaceURI + { + get + { + return GetMappedNamespace(Reader.NamespaceURI); + } + } + + /// + /// Gets the depth of the current node in the XML document. + /// + public override int Depth + { + get + { + return Reader.Depth - _depthOffset; + } + } + + /// + /// Gets a value indicating whether the current node has any attributes + /// + public override bool HasAttributes + { + get + { + return AttributeCount != 0; + } + } + + /// + /// Gets the number of attributes on the current node. + /// + public override int AttributeCount + { + get + { + return Reader.AttributeCount - _ignoredAttributeCount; + } + } + + /// + /// Sets a value indicating whether to normalize white space and attribute values. + /// + public bool Normalization + { + set + { + XmlTextReader xmlTextReader = Reader as XmlTextReader; + + // review, what if not the XmlTextReader. + if (null != xmlTextReader) + { + xmlTextReader.Normalization = value; + } + } + } + +#if !PBTCOMPILER + /// + /// Answer the encoding of the underlying xaml stream + /// + internal System.Text.Encoding Encoding + { + get + { + XmlTextReader textReader = Reader as XmlTextReader; + if (textReader == null) + { + return new System.Text.UTF8Encoding(true, true); + } + else + { + return textReader.Encoding; + } + } + } +#endif + #endregion Public Properties + + #region Private Methods + + private void SaveReaderPosition() + { + // Save current state so we can go back to the same spot if this fails + _inAttribute = (Reader.NodeType == XmlNodeType.Attribute); + _currentName = Reader.Name; + } + + private void RestoreReaderPosition() + { + // Restore reader state from SaveReaderPosition + if (_inAttribute) + { + Reader.MoveToAttribute(_currentName); + } + else + { + Reader.MoveToElement(); + } + } + + /// + /// Retrieves the correctly mapped namespace from the namespace provided + /// + /// + /// The name of the namespace to retrieve the mapping of + /// + /// + /// The name of the mapped namespace. + /// + private string GetMappedNamespace(string namespaceName) + { + string mappedNamespace; + + // if the namespace is not null, get the mapped namespace (which may be itself) + if (!_namespaceMap.TryGetValue(namespaceName, out mappedNamespace)) + { + // if the namespace has not yet been mapped, map it + mappedNamespace = MapNewNamespace(namespaceName); + } + else if (mappedNamespace == null) + { + // if the mapped namespace is null, then the namespace was not supported, just return + // the given namespace + mappedNamespace = namespaceName; + } + + return mappedNamespace; + } + + /// + /// Adds the namespace to the namespace map. The default is to map the namespace to itself. + /// The namespace is mapped to the value returned by the callback, if a callback exists and the + /// callback returns a subsuming namespace. + /// + /// + /// The name of the namespace to be mapped. + /// + /// + /// The name of the mapped namespace. + /// + private string MapNewNamespace(string namespaceName) + { + if (_namespaceCallback != null) + { + string mappedNamespace; + + // the callback returns whether the namespace is supported, and mappedNamespace is the + // namespace subsuming the namespace passed in. + bool isSupported = _namespaceCallback(namespaceName, out mappedNamespace); + + if (isSupported) + { + AddKnownNamespace(namespaceName); + + if (String.IsNullOrEmpty(mappedNamespace) || namespaceName == mappedNamespace) + { + _namespaceMap[namespaceName] = namespaceName; + } + else + { + // subsume namespace with mappedNamespace. + string tempNamespace; + + if (!_namespaceMap.TryGetValue(mappedNamespace, out tempNamespace)) + { + // If the namespace is known, but doesn't have a map, that means we're + // already in the process of calling MapNewNamespace on it, i.e. we have + // a cycle + if (IsNamespaceKnown(mappedNamespace)) + { + Error(SR.Get(SRID.XCRCompatCycle), mappedNamespace); + } + + // mappedNamespace has not been mapped, so map it + tempNamespace = MapNewNamespace(mappedNamespace); + } + + DeclareNamespaceCompatibility(tempNamespace, namespaceName); + namespaceName = tempNamespace; + } + } + else + { + // if the namespace is not supported, we enter null into the namespaceMap as a placeholder + // so that we do not call the callback again on this namespace. + _namespaceMap[namespaceName] = null; + } + } + + return namespaceName; + } + + /// + /// Used to determine whether a given namespace subsumes another namespace + /// + /// + /// The name of the namespace to be checked. + /// + /// + /// true if the namespace subsumes another namespace; false otherwise + /// + private bool IsSubsumingNamespace(string namespaceName) + { + return (_subsumingNamespaces == null ? false : _subsumingNamespaces.ContainsKey(namespaceName)); + } + + /// + /// Used to specify that a namespace subsumes another namespace + /// + /// + /// The name of the namespace to be added. + /// + private void AddSubsumingNamespace(string namespaceName) + { + if (_subsumingNamespaces == null) + _subsumingNamespaces = new Dictionary(); + _subsumingNamespaces[namespaceName] = null; + } + + /// + /// Used to determine whether a given namespace is known/supported + /// + /// + /// The name of the namespace to be checked. + /// + /// + /// true if the namespace is known/supported; false otherwise + /// + private bool IsNamespaceKnown(string namespaceName) + { + return (_knownNamespaces == null ? false : _knownNamespaces.ContainsKey(namespaceName)); + } + + /// + /// Used to specify that a namespace is known or supported + /// + /// + /// The name of the namespace to be added. + /// + private void AddKnownNamespace(string namespaceName) + { + if (_knownNamespaces == null) + _knownNamespaces = new Dictionary(); + _knownNamespaces[namespaceName] = null; + } + + /// + /// Used to determine whether a given namespace should be ignored. A namespace should be ignored if: + /// EITHER + /// a) the namespace is not known/supported and has been marked Ignorable + /// OR + /// b) the namespace is the markup-compatibility namespace + /// + /// + /// The name of the prefix to be checked. + /// + /// + /// true if the namespace should be ignored; false otherwise + /// + private bool ShouldIgnoreNamespace(string namespaceName) + { + bool result; + if (IsNamespaceKnown(namespaceName)) + { + result = object.ReferenceEquals(namespaceName, CompatibilityUri); + } + else + { + result = Scope.CanIgnore(namespaceName); + } + return result; + } + + /// + /// breaks up a space-delineated string into namespace/element pairs + /// + /// + /// the string to be parsed + /// + /// + /// The calling element, used in case of an error + /// + /// + /// the list of namespace/element pairs + /// + private IEnumerable ParseContentToNamespaceElementPair(string content, string callerContext) + { + foreach (string pair in content.Trim().Split(' ')) + { + // check each non-null, non-empty space-delineated namespace/element pair + if (!String.IsNullOrEmpty(pair)) + { + int colonIndex = pair.IndexOf(':'); + int length = pair.Length; + + if (colonIndex <= 0 || colonIndex >= length - 1 || colonIndex != pair.LastIndexOf(':')) + { + // if string does not have a ':', if the last character in the string is a ':' + // or if the string contains more than one ':', throw an exception + Error(SR.Get(SRID.XCRInvalidFormat), callerContext); + } + + string prefix = pair.Substring(0, colonIndex); + string elementName = pair.Substring(colonIndex + 1, length - 1 - colonIndex); + string namespaceName = LookupNamespace(prefix); + + if (namespaceName == null) + { + // if a prefix does not map to a namespace, throw an exception + Error(SR.Get(SRID.XCRUndefinedPrefix), prefix); + } + else if (elementName != "*" && !IsName(elementName)) + { + // if the element's name is not valid XML, throw an exception + Error(SR.Get(SRID.XCRInvalidXMLName), pair); + } + else + { + yield return new NamespaceElementPair(namespaceName, elementName); + } + } + } + } + + /// + /// converts a string of space-delineated prefixes into a list of namespaces + /// + /// + /// the string to be parsed + /// + /// + /// the list of namespace/element pairs + /// + private IEnumerable PrefixesToNamespaces(string prefixes) + { + foreach (string prefix in prefixes.Trim().Split(' ')) + { + // check each non-null, non-empty space-delineated prefix + if (!String.IsNullOrEmpty(prefix)) + { + string namespaceUri = LookupNamespace(prefix); + + if (namespaceUri == null) + { + // if a prefix does not map to a namespace, throw an exception + Error(SR.Get(SRID.XCRUndefinedPrefix), prefix); + } + else + { + yield return namespaceUri; + } + } + } + } + + /// + /// advances the reader to the next known namespace/attribute pair + /// + /// + /// true if a known namespace/attribute pair was found + /// + private bool SkipToKnownAttribute() + { + bool result = true; + while (result && ShouldIgnoreNamespace(NamespaceURI)) + { + result = Reader.MoveToNextAttribute(); + } + return result; + } + + /// + /// Scans the current element for compatibility attributes. Pushes a new + /// scope onto the stack under the following conditions: + /// 1) Ignorable or MustUnderstand attribute read + /// 2) current element has not previously declared an Ignorable or + /// MustUnderstand attribute + /// + /// However, if a last condition is not fulfilled, then the scope is popped off + /// before the function returns + /// 3) current element is not empty + /// + /// stores in _ignoredAttributeCount the number of attributes on the current element + /// that should be ignored, for the sake of improving perf in attribute-related + /// methods/properties + /// + /// + /// the depth of the Reader at the element currently being processed + /// + private void ScanForCompatibility(int elementDepth) + { + bool onAttribute = Reader.MoveToFirstAttribute(); + + _ignoredAttributeCount = 0; + + if (onAttribute) + { + _attributePosition = 0; // we count the attribute index in case we see Ignorable + + do + { + string namespaceName = NamespaceURI; + + if (ShouldIgnoreNamespace(namespaceName)) + { + // check each attribute's namespace to see if it should be ignored + if (object.ReferenceEquals(namespaceName, CompatibilityUri)) + { + // if the attribute is in the markup-compatibility namespace + // find and call the appropriate attribute handler callback. + string attributeName = Reader.LocalName; + HandleAttributeCallback attributeCB; + if (!_attributeHandler.TryGetValue(attributeName, out attributeCB)) + { + Error(SR.Get(SRID.XCRUnknownCompatAttrib), attributeName); + } + attributeCB(elementDepth); + } + + _ignoredAttributeCount++; + } + + onAttribute = Reader.MoveToNextAttribute(); + _attributePosition++; // we count the attribute index in case we see Ignorable + } while (onAttribute); + + if (Scope.Depth == elementDepth) + { + // if this element pushed a scope, then we need to do a sanity check + Scope.Verify(); + } + + // move the reader back to the element for the client + Reader.MoveToElement(); + } + } + + + /// + /// pops a scope if the end of a compatibility region. + /// + /// + /// the depth of the Reader at the element currently being processed + /// + private void ScanForEndCompatibility(int elementDepth) + { + if (elementDepth == Scope.Depth) + { + // if the current element's depth equals the depth of the top-level scope, then pop + PopScope(); + } + } + + /// + /// pushes a new scope onto the stack with a depth passed as an arg. + /// PushScope does not push a scope if the top scope on the stack is not a lower depth. + /// + /// + /// the depth of the Reader at the element currently being processed + /// + private void PushScope(int elementDepth) + { + if (_compatibilityScope.Depth < elementDepth) + { + // if the current element has already pushed a scope, then don't push another one + _compatibilityScope = new CompatibilityScope(_compatibilityScope, elementDepth, this); + } + } + + /// + /// pops a scope off the top of the stack. + /// PopScope *always* pops, it does not check the depth before doing so + /// + private void PopScope() + { + _compatibilityScope = _compatibilityScope.Previous; + } + + /// + /// handles mc:AlternateContent element + /// + /// a good way to think of AlternateContent blocks is as a switch/case + /// statement. The AlternateContent tag is like switch, Choice is like + /// case, and Fallback is like default. + /// + /// + /// the depth of the Reader at the element currently being processed + /// + /// + /// returns whether the Reader has more to be read + /// + private void HandleAlternateContent(int elementDepth, ref bool more) + { + if (Scope.InAlternateContent) + { + // the only valid tags within ... are + // Choice and Fallback + Error(SR.Get(SRID.XCRInvalidACChild, Reader.Name)); + } + if (Reader.IsEmptyElement) + { + // AlternateContent blocks must have a Choice, so they can't be empty + Error(SR.Get(SRID.XCRChoiceNotFound)); + } + + // check for markup-compatibility attributes, then push an AlternateContent scope + ScanForCompatibility(elementDepth); + PushScope(elementDepth); + + Scope.InAlternateContent = true; + _depthOffset++; + more = Reader.Read(); + } + + /// + /// handles mc:Choice element + /// + /// a good way to think of AlternateContent blocks is as a switch/case + /// statement. The AlternateContent tag is like switch, Choice is like + /// case, and Fallback is like default. + /// + /// + /// the depth of the Reader at the element currently being processed + /// + /// + /// returns whether the Reader has more to be read + /// + private void HandleChoice(int elementDepth, ref bool more) + { + if (!Scope.InAlternateContent) + { + // Choice must be the child of AlternateContent + Error(SR.Get(SRID.XCRChoiceOnlyInAC)); + } + if (Scope.FallbackSeen) + { + // Choice cannot occur after Fallback + Error(SR.Get(SRID.XCRChoiceAfterFallback)); + } + + string requiresValue = Reader.GetAttribute(Requires); + + if (requiresValue == null) + { + // Choice must have a requires attribute + Error(SR.Get(SRID.XCRRequiresAttribNotFound)); + } + if (String.IsNullOrEmpty(requiresValue)) + { + // Requires attribute may not be empty + Error(SR.Get(SRID.XCRInvalidRequiresAttribute)); + } + + CompatibilityScope scope = Scope; + + // check for markup-compatibility attributes + ScanForCompatibility(elementDepth); + + if (AttributeCount != 1) + { + // Choice may not have any attribute that should not be ignored other than Requires + // get first non-markup-compatibility, non-Requires attribute + MoveToFirstAttribute(); + if (Reader.LocalName == Requires) + { + MoveToNextAttribute(); + } + string attributeName = Reader.LocalName; + MoveToElement(); + + Error(SR.Get(SRID.XCRInvalidAttribInElement), attributeName, Choice); + } + + if (scope.ChoiceTaken) + { + // a previous choice was valid, so pop any scope pushed and + // skip to next attribute after + ScanForEndCompatibility(elementDepth); + Reader.Skip(); + } + else + { + // mark AlternateContent as having seen a choice + scope.ChoiceSeen = true; + + bool allKnown = true; + bool somethingSeen = false; + + foreach (string namespaceUri in PrefixesToNamespaces(requiresValue)) + { + somethingSeen = true; + if (!IsNamespaceKnown(namespaceUri)) + { + // if any attribute in the Requires value is unknown, then do not take this choice + allKnown = false; + break; + } + } + + if (!somethingSeen) + { + // if the Requires value does not contain a valid prefix/namespace, throw an exception + Error(SR.Get(SRID.XCRInvalidRequiresAttribute)); + } + + if (allKnown) + { + // if all namespace in the Requires value are known, then this is the Choice taken. + // Mark AlternateContent scope as having taken a choice + scope.ChoiceTaken = true; + + // we push a scope here as a place holder, because AlternateContent + // scopes do not allow child elements other than Choice and Fallback + PushScope(elementDepth); + _depthOffset++; + more = Reader.Read(); + } + else + { + // this is not the choice taken, so pop any scope pushed and + // skip to next attribute after + ScanForEndCompatibility(elementDepth); + Reader.Skip(); + } + } + } + + /// + /// handles mc:Fallback element + /// + /// a good way to think of AlternateContent blocks is as a switch/case + /// statement. The AlternateContent tag is like switch, Choice is like + /// case, and Fallback is like default. + /// + /// + /// the depth of the Reader at the element currently being processed + /// + /// + /// returns whether the Reader has more to be read + /// + private void HandleFallback(int elementDepth, ref bool more) + { + if (!Scope.InAlternateContent) + { + // Fallback must be the child of AlternateContent + Error(SR.Get(SRID.XCRFallbackOnlyInAC)); + } + if (!Scope.ChoiceSeen) + { + // AlternateContent block must contain a Choice element + Error(SR.Get(SRID.XCRChoiceNotFound)); + } + if (Scope.FallbackSeen) + { + // AlternateContent block may only contain one Fallback child + Error(SR.Get(SRID.XCRMultipleFallbackFound)); + } + + // mark scope as having a fallback + Scope.FallbackSeen = true; + bool choiceTaken = Scope.ChoiceTaken; + + // check for markup-compatibility attributes + ScanForCompatibility(elementDepth); + + if (AttributeCount != 0) + { + // Fallback may not have any attribute that should not be ignored + // get first non-markup-compatibility attribute + MoveToFirstAttribute(); + string attributeName = Reader.LocalName; + MoveToElement(); + + Error(SR.Get(SRID.XCRInvalidAttribInElement), attributeName, Fallback); + } + + if (choiceTaken) + { + // a choice was valid, so ignore contents + ScanForEndCompatibility(elementDepth); + Reader.Skip(); + } + else + { + // this is the content that will be used, so push a scope + if (!Reader.IsEmptyElement) + { + // we push a scope here as a place holder, because AlternateContent + // scopes do not allow child elements other than Choice and Fallback + PushScope(elementDepth); + _depthOffset++; + } + more = Reader.Read(); + } + } + + /// + /// handles mc:Ignorable="foo" attribute + /// + /// Ignorable is used to indicate that the namespace the prefix is mapped to can + /// be ignored, i.e. when the namespace/element or namespace/attribute occurs it + /// is not returned by the reader. + /// + private void HandleIgnorable(int elementDepth) + { + PushScope(elementDepth); + + foreach (string namespaceUri in PrefixesToNamespaces(Reader.Value)) + { + Scope.Ignorable(namespaceUri); + } + + // Just in case one of the namespaces that preceded the Ignorable declaration + // was an ignorable namespace, we have to recompute _ignoredAttributeCount. + // No need to check if we haven't yet had any non-ignored attributes. + if (_ignoredAttributeCount < _attributePosition) + { + _ignoredAttributeCount = 0; + Reader.MoveToFirstAttribute(); + + for (int i = 0; i < _attributePosition; i++) + { + if (ShouldIgnoreNamespace(Reader.NamespaceURI)) + { + _ignoredAttributeCount++; + } + + Reader.MoveToNextAttribute(); + } + } + } + + /// + /// handles mc:MustUnderstand="foo" attribute + /// + /// MustUnderstand is used to indicate that the namespace the prefix is mapped to + /// cannot be handled, and if it is not understood an exception is thrown + /// + private void HandleMustUnderstand(int elementDepth) + { + foreach (string namespaceUri in PrefixesToNamespaces(Reader.Value)) + { + if (!IsNamespaceKnown(namespaceUri)) + { + Error(SR.Get(SRID.XCRMustUnderstandFailed), namespaceUri); + } + } + } + + /// + /// handles mc:ProcessContent="foo:bar" attribute + /// + /// ProcessContent is used to indicate that an ignorable namespace has some + /// elements that should be skipped, but contain child elements that should be processed. + /// + /// The wildcard token ("foo:*") indicates that the children of any element in that + /// namespace should be processed. + /// + private void HandleProcessContent(int elementDepth) + { + PushScope(elementDepth); + + foreach (NamespaceElementPair pair in ParseContentToNamespaceElementPair(Reader.Value, _processContent)) + { + Scope.ProcessContent(pair.namespaceName, pair.itemName); + } + } + + /// + /// handles mc:PreserveElements="foo:bar" attribute + /// + /// functionality is supported, but not implemented + /// + private void HandlePreserveElements(int elementDepth) + { + PushScope(elementDepth); + + foreach (NamespaceElementPair pair in ParseContentToNamespaceElementPair(Reader.Value, _preserveElements)) + { + Scope.PreserveElement(pair.namespaceName, pair.itemName); + } + } + + /// + /// handles mc:PreserveAttributes="foo:bar" attribute + /// + /// functionality is supported, but not implemented + /// + private void HandlePreserveAttributes(int elementDepth) + { + PushScope(elementDepth); + + foreach (NamespaceElementPair pair in ParseContentToNamespaceElementPair(Reader.Value, _preserveAttributes)) + { + Scope.PreserveAttribute(pair.namespaceName, pair.itemName); + } + } + + /// + /// helper method to generate an exception + /// + private void Error(string message, params object[] args) + { + IXmlLineInfo info = Reader as IXmlLineInfo; + throw new XmlException(string.Format(CultureInfo.InvariantCulture, message, args), null, info == null ? 1 : info.LineNumber, + info == null ? 1 : info.LinePosition); + } + #endregion Private Methods + + #region Private Properties + private CompatibilityScope Scope + { + get + { + return _compatibilityScope; + } + } + + private string AlternateContent + { + get + { + if (_alternateContent == null) + { + _alternateContent = Reader.NameTable.Add("AlternateContent"); + } + return _alternateContent; + } + } + + private string Choice + { + get + { + if (_choice == null) + { + _choice = Reader.NameTable.Add("Choice"); + } + return _choice; + } + } + + private string Fallback + { + get + { + if (_fallback == null) + { + _fallback = Reader.NameTable.Add("Fallback"); + } + return _fallback; + } + } + + private string Requires + { + get + { + if (_requires == null) + { + _requires = Reader.NameTable.Add("Requires"); + } + return _requires; + } + } + + private string Ignorable + { + get + { + if (_ignorable == null) + { + _ignorable = Reader.NameTable.Add("Ignorable"); + } + return _ignorable; + } + } + + private string MustUnderstand + { + get + { + if (_mustUnderstand == null) + { + _mustUnderstand = Reader.NameTable.Add("MustUnderstand"); + } + return _mustUnderstand; + } + } + + private string ProcessContent + { + get + { + if (_processContent == null) + { + _processContent = Reader.NameTable.Add("ProcessContent"); + } + return _processContent; + } + } + + private string PreserveElements + { + get + { + if (_preserveElements == null) + { + _preserveElements = Reader.NameTable.Add("PreserveElements"); + } + return _preserveElements; + } + } + + private string PreserveAttributes + { + get + { + if (_preserveAttributes == null) + { + _preserveAttributes = Reader.NameTable.Add("PreserveAttributes"); + } + return _preserveAttributes; + } + } + + private string CompatibilityUri + { + get + { + if (_compatibilityUri == null) + { + _compatibilityUri = Reader.NameTable.Add(MarkupCompatibilityURI); + } + return _compatibilityUri; + } + } + #endregion Private Properties + #region Nested Classes + struct NamespaceElementPair + { + public string namespaceName; + public string itemName; + + public NamespaceElementPair(string namespaceName, string itemName) + { + this.namespaceName = namespaceName; + this.itemName = itemName; + } + } + + /// + /// CompatibilityScopes are used to handle markup-compatibility elements and attributes. + /// Each scope stores the "previous" or parent scope, its depth, and an associated XmlCompatibilityReader. + /// At a particular Reader depth, only one scope should be pushed. + /// + private class CompatibilityScope + { + CompatibilityScope _previous; + int _depth; + bool _fallbackSeen; + bool _inAlternateContent; + bool _inProcessContent; + bool _choiceTaken; + bool _choiceSeen; + XmlCompatibilityReader _reader; + Dictionary _ignorables; + Dictionary _processContents; + Dictionary _preserveElements; + Dictionary _preserveAttributes; + + public CompatibilityScope(CompatibilityScope previous, int depth, XmlCompatibilityReader reader) + { + _previous = previous; + _depth = depth; + _reader = reader; + } + + public CompatibilityScope Previous + { + get + { + return _previous; + } + } + + public int Depth + { + get + { + return _depth; + } + } + + public bool FallbackSeen + { + get + { + bool result; + if (_inProcessContent && _previous != null) + { + result = _previous.FallbackSeen; + } + else + { + result = _fallbackSeen; + } + return result; + } + set + { + if (_inProcessContent && _previous != null) + { + _previous.FallbackSeen = value; + } + else + { + _fallbackSeen = value; + } + } + } + + public bool InAlternateContent + { + get + { + bool result; + if (_inProcessContent && _previous != null) + { + result = _previous.InAlternateContent; + } + else + { + result = _inAlternateContent; + } + return result; + } + set + { + _inAlternateContent = value; + } + } + + public bool InProcessContent + { + set + { + _inProcessContent = value; + } + } + + public bool ChoiceTaken + { + get + { + bool result; + if (_inProcessContent && _previous != null) + { + result = _previous.ChoiceTaken; + } + else + { + result = _choiceTaken; + } + return result; + } + set + { + if (_inProcessContent && _previous != null) + { + _previous.ChoiceTaken = value; + } + else + { + _choiceTaken = value; + } + } + } + + public bool ChoiceSeen + { + get + { + bool result; + if (_inProcessContent && _previous != null) + { + result = _previous.ChoiceSeen; + } + else + { + result = _choiceSeen; + } + return result; + } + set + { + if (_inProcessContent && _previous != null) + { + _previous.ChoiceSeen = value; + } + else + { + _choiceSeen = value; + } + } + } + + public bool CanIgnore(string namespaceName) + { + bool result = IsIgnorableAtCurrentScope(namespaceName); + + if (!result && _previous != null) + { + result = _previous.CanIgnore(namespaceName); + } + + return result; + } + + public bool IsIgnorableAtCurrentScope(string namespaceName) + { + return _ignorables != null && _ignorables.ContainsKey(namespaceName); + } + + public bool ShouldProcessContent(string namespaceName, string elementName) + { + bool result = false; + ProcessContentSet set; + if (_processContents != null && _processContents.TryGetValue(namespaceName, out set)) + { + result = set.ShouldProcessContent(elementName); + } + else if (_previous != null) + { + result = _previous.ShouldProcessContent(namespaceName, elementName); + } + + return result; + } + + public void Ignorable(string namespaceName) + { + if (_ignorables == null) + { + _ignorables = new Dictionary(); + } + _ignorables[namespaceName] = null; // we don't care about value, just key + } + + public void ProcessContent(string namespaceName, string elementName) + { + if (_processContents == null) + { + _processContents = new Dictionary(); + } + ProcessContentSet processContentSet; + if (!_processContents.TryGetValue(namespaceName, out processContentSet)) + { + processContentSet = new ProcessContentSet(namespaceName, _reader); + _processContents.Add(namespaceName, processContentSet); + } + processContentSet.Add(elementName); + } + + public void PreserveElement(string namespaceName, string elementName) + { + if (_preserveElements == null) + { + _preserveElements = new Dictionary(); + } + PreserveItemSet preserveElementSet; + if (!_preserveElements.TryGetValue(namespaceName, out preserveElementSet)) + { + preserveElementSet = new PreserveItemSet(namespaceName, _reader); + _preserveElements.Add(namespaceName, preserveElementSet); + } + preserveElementSet.Add(elementName); + } + + public void PreserveAttribute(string namespaceName, string attributeName) + { + if (_preserveAttributes == null) + { + _preserveAttributes = new Dictionary(); + } + PreserveItemSet preserveAttributeSet; + if (!_preserveAttributes.TryGetValue(namespaceName, out preserveAttributeSet)) + { + preserveAttributeSet = new PreserveItemSet(namespaceName, _reader); + _preserveAttributes.Add(namespaceName, preserveAttributeSet); + } + preserveAttributeSet.Add(attributeName); + } + + /*public bool ShouldPreserveElement(string namespaceName, string elementName) + { + bool result = _preserveItems != null && _preserveItems.ShouldPreserveElement(namespaceName, elementName); + if (!result && _previous != null) + result = _previous.ShouldPreserveElement(namespaceName, elementName); + return result; + } + + public bool ShouldPreserveAttribute(string namespaceName, string attributeName) + { + bool result = _preserveItems != null && _preserveItems.ShouldPreserveAttribute(namespaceName, attributeName); + if (!result && _previous != null) + result = _previous.ShouldPreserveAttribute(namespaceName, attributeName); + return result; + }*/ + + public void Verify() + { + // Check process content + if (_processContents != null) + { + foreach (string key in _processContents.Keys) + { + if (!IsIgnorableAtCurrentScope(key)) + { + _reader.Error(SR.Get(SRID.XCRNSProcessContentNotIgnorable), key); + } + } + } + // Check preserve elements + if (_preserveElements != null) + { + foreach (string key in _preserveElements.Keys) + { + if (!IsIgnorableAtCurrentScope(key)) + { + _reader.Error(SR.Get(SRID.XCRNSPreserveNotIgnorable), key); + } + } + } + // Check preserve attributes + if (_preserveAttributes != null) + { + foreach (string key in _preserveAttributes.Keys) + { + if (!IsIgnorableAtCurrentScope(key)) + { + _reader.Error(SR.Get(SRID.XCRNSPreserveNotIgnorable), key); + } + } + } + } + } + + class ProcessContentSet + { + bool _all; + string _namespaceName; + XmlCompatibilityReader _reader; + Dictionary _names; + + public ProcessContentSet(string namespaceName, XmlCompatibilityReader reader) + { + _namespaceName = namespaceName; + _reader = reader; + } + + public bool ShouldProcessContent(string elementName) + { + return _all || (_names != null && _names.ContainsKey(elementName)); + } + + public void Add(string elementName) + { + if (ShouldProcessContent(elementName)) + { + if (elementName == "*") + { + _reader.Error(SR.Get(SRID.XCRDuplicateWildcardProcessContent), _namespaceName); + } + else + { + _reader.Error(SR.Get(SRID.XCRDuplicateProcessContent), _namespaceName, elementName); + } + } + + if (elementName == "*") + { + if (_names != null) + { + _reader.Error(SR.Get(SRID.XCRInvalidProcessContent), _namespaceName); + } + else + { + _all = true; + } + } + else + { + if (_names == null) + { + _names = new Dictionary(); + } + + _names[elementName] = null; // we don't care about value, just key + } + } + + } + + class PreserveItemSet + { + bool _all; + string _namespaceName; + XmlCompatibilityReader _reader; + Dictionary _names; + + public PreserveItemSet(string namespaceName, XmlCompatibilityReader reader) + { + _namespaceName = namespaceName; + _reader = reader; + } + + public bool ShouldPreserveItem(string itemName) + { + return _all || (_names != null && _names.ContainsKey(itemName)); + } + + public void Add(string itemName) + { + if (ShouldPreserveItem(itemName)) + { + if (itemName == "*") + { + _reader.Error(SR.Get(SRID.XCRDuplicateWildcardPreserve), _namespaceName); + } + else + { + _reader.Error(SR.Get(SRID.XCRDuplicatePreserve), itemName, _namespaceName); + } + } + + if (itemName == "*") + { + if (_names != null) + { + _reader.Error(SR.Get(SRID.XCRInvalidPreserve), _namespaceName); + } + else + { + _all = true; + } + } + else + { + if (_names == null) + { + _names = new Dictionary(); + } + + _names.Add(itemName, itemName); + } + } + } + #endregion Nested Classes + + #region Private Fields + private bool _inAttribute; // for Save/Restore ReaderPosition + private string _currentName; // for Save/Restore ReaderPosition + private IsXmlNamespaceSupportedCallback _namespaceCallback; + private Dictionary _knownNamespaces; + private Dictionary _namespaceMap = new Dictionary(); + private Dictionary _subsumingNamespaces; + private Dictionary _elementHandler = new Dictionary(); + private Dictionary _attributeHandler = new Dictionary(); + private int _depthOffset; // offset for Depth method, to account for elements that should be ignored by client + private int _ignoredAttributeCount; + private int _attributePosition; // used for ScanForCompatibility / HandleIgnorable + private string _compatibilityUri; + private string _alternateContent; + private string _choice; + private string _fallback; + private string _requires; + private string _ignorable; + private string _mustUnderstand; + private string _processContent; + private string _preserveElements; + private string _preserveAttributes; + private CompatibilityScope _compatibilityScope; + + private bool isPreviousElementEmpty; + private int previousElementDepth; + + private const string XmlnsDeclaration = "xmlns"; + private const string MarkupCompatibilityURI = "http://schemas.openxmlformats.org/markup-compatibility/2006"; + + static private string[] _predefinedNamespaces = new string[4] { + "http://www.w3.org/2000/xmlns/", + "http://www.w3.org/XML/1998/namespace", + "http://www.w3.org/2001/XMLSchema-instance", + MarkupCompatibilityURI + }; + #endregion Private Fields + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/XmlWrappingReader.cs b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/XmlWrappingReader.cs new file mode 100644 index 00000000000..ace5889f7c7 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/XmlWrappingReader.cs @@ -0,0 +1,188 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System; +using System.Xml; +using System.Xml.Schema; +using System.Diagnostics; +using System.Collections.Generic; +using System.Security.Policy; + +#if PBTCOMPILER +namespace MS.Internal.Markup +#elif SYSTEM_XAML +namespace System.Xaml +#else +namespace System.Windows.Markup +#endif +{ + + internal class XmlWrappingReader : XmlReader, IXmlLineInfo, IXmlNamespaceResolver { +// +// Fields +// + protected XmlReader _reader; + protected IXmlLineInfo _readerAsIXmlLineInfo; + protected IXmlNamespaceResolver _readerAsResolver; + +// +// Constructor +// + internal XmlWrappingReader( XmlReader baseReader ) { + Debug.Assert( baseReader != null ); + Reader = baseReader; + } + +// +// XmlReader implementation +// + public override XmlReaderSettings Settings { get { return _reader.Settings; } } + public override XmlNodeType NodeType { get { return _reader.NodeType; } } + public override string Name { get { return _reader.Name; } } + public override string LocalName { get { return _reader.LocalName; } } + public override string NamespaceURI { get { return _reader.NamespaceURI; } } + public override string Prefix { get { return _reader.Prefix; } } + public override bool HasValue { get { return _reader.HasValue; } } + public override string Value { get { return _reader.Value; } } + public override int Depth { get { return _reader.Depth; } } + public override string BaseURI { get { return _reader.BaseURI; } } + public override bool IsEmptyElement { get { return _reader.IsEmptyElement; } } + public override bool IsDefault { get { return _reader.IsDefault; } } + public override char QuoteChar { get { return _reader.QuoteChar; } } + public override XmlSpace XmlSpace { get { return _reader.XmlSpace; } } + public override string XmlLang { get { return _reader.XmlLang; } } + public override IXmlSchemaInfo SchemaInfo { get { return _reader.SchemaInfo; } } + public override System.Type ValueType { get { return _reader.ValueType; } } + public override int AttributeCount { get { return _reader.AttributeCount; } } + public override string this [ int i ] { get { return _reader[i]; } } + public override string this [ string name ] { get { return _reader[ name ];}} + public override string this [ string name, string namespaceURI ] { get { return _reader[ name, namespaceURI ]; } } + public override bool CanResolveEntity { get { return _reader.CanResolveEntity; } } + public override bool EOF { get { return _reader.EOF; } } + public override ReadState ReadState { get { return _reader.ReadState; } } + public override bool HasAttributes { get { return _reader.HasAttributes; } } + public override XmlNameTable NameTable { get { return _reader.NameTable; } } + + public override string GetAttribute( string name ) { + return _reader.GetAttribute( name ); + } + + public override string GetAttribute( string name, string namespaceURI ) { + return _reader.GetAttribute( name, namespaceURI ); + } + + public override string GetAttribute( int i ) { + return _reader.GetAttribute( i ); + } + + public override bool MoveToAttribute( string name ) { + return _reader.MoveToAttribute( name ); + } + + public override bool MoveToAttribute( string name, string ns ) { + return _reader.MoveToAttribute( name, ns ); + } + + public override void MoveToAttribute( int i ) { + _reader.MoveToAttribute( i ); + } + + public override bool MoveToFirstAttribute() { + return _reader.MoveToFirstAttribute(); + } + + public override bool MoveToNextAttribute() { + return _reader.MoveToNextAttribute(); + } + + public override bool MoveToElement() { + return _reader.MoveToElement(); + } + + public override bool Read() { + return _reader.Read(); + } + + public override void Close() { + _reader.Close(); + } + + public override void Skip() { + _reader.Skip(); + } + + public override string LookupNamespace( string prefix ) { + return _reader.LookupNamespace( prefix ); + } + + string IXmlNamespaceResolver.LookupPrefix( string namespaceName ) { + return (_readerAsResolver == null) ? null : _readerAsResolver.LookupPrefix( namespaceName ); + } + + IDictionary IXmlNamespaceResolver.GetNamespacesInScope ( XmlNamespaceScope scope ) { + return (_readerAsResolver == null) ? null : _readerAsResolver.GetNamespacesInScope( scope ); + } + + public override void ResolveEntity() { + _reader.ResolveEntity(); + } + + public override bool ReadAttributeValue() { + return _reader.ReadAttributeValue(); + } + +// +// IDisposable interface +// + protected override void Dispose(bool disposing) { + try + { + if(disposing) + { + ((IDisposable)_reader).Dispose(); + } + } + finally + { + base.Dispose(disposing); + } + } + +// +// IXmlLineInfo members +// + public virtual bool HasLineInfo() { + return ( _readerAsIXmlLineInfo == null ) ? false : _readerAsIXmlLineInfo.HasLineInfo(); + } + + public virtual int LineNumber { + get { + return ( _readerAsIXmlLineInfo == null ) ? 0 : _readerAsIXmlLineInfo.LineNumber; + } + } + + public virtual int LinePosition { + get { + return ( _readerAsIXmlLineInfo == null ) ? 0 : _readerAsIXmlLineInfo.LinePosition; + } + } + +// +// Protected methods +// + protected XmlReader Reader { + get { + return _reader; + } + set { + _reader = value; + _readerAsIXmlLineInfo = value as IXmlLineInfo; + _readerAsResolver = value as IXmlNamespaceResolver; + } + } + } +} + + diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Media/TypeConverterHelper.cs b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Media/TypeConverterHelper.cs new file mode 100644 index 00000000000..32150b95f2e --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Media/TypeConverterHelper.cs @@ -0,0 +1,115 @@ +//------------------------------------------------------------------------------ +// Microsoft Avalon +// Copyright (c) Microsoft Corporation, All rights reserved. +// +// File: TypeConverterHelper.cs +// +//------------------------------------------------------------------------------ +using System; +using System.Diagnostics; +using System.ComponentModel; +using System.Windows.Markup; +using System.Runtime.InteropServices; +using System.Windows.Navigation; + +namespace System.Windows.Media +{ + #region UriHolder + + /// + /// UriHolder + /// Holds Original and Base Uris + /// + [StructLayout(LayoutKind.Sequential, Pack=1)] + internal struct UriHolder + { + + /// + /// BaseUri + /// Can be null + /// + internal Uri BaseUri; + + /// + /// OriginalUri + /// + internal Uri OriginalUri; + }; + + #endregion + + #region TypeConverterHelper + + /// + /// This helper method is used primarily by type converters to resolve their uri + /// + /// + /// There are three scenarios that can happen: + /// + /// 1) inputString is an absolute uri -- we return it as the resolvedUri + /// 2) inputString is not absolute: + /// i) the relativeBaseUri (obtained from IUriContext) has the following values: + /// a) is an absolute uri, we use relativeBaseUri as base uri and resolve + /// the inputString against it + /// + /// b) is a relative uri, we use Application's base uri (obtained from + /// BindUriHelperCore.BaseUri) as the base and resolve the relativeBaseUri + /// against it; furthermore, we resolve the inputString against with uri + /// obtained from the application base resolution. + /// + /// c) is "", we resolve inputString against the Application's base uri + /// + internal static class TypeConverterHelper + { + internal static UriHolder GetUriFromUriContext(ITypeDescriptorContext context, object inputString) + { + UriHolder uriHolder = new UriHolder(); + + if (inputString is string) + { + uriHolder.OriginalUri = new Uri((string)inputString, UriKind.RelativeOrAbsolute); + } + else + { + Debug.Assert(inputString is Uri); + uriHolder.OriginalUri = (Uri)inputString; + } + + if (uriHolder.OriginalUri.IsAbsoluteUri == false) + { + //Debug.Assert (context != null, "Context should not be null"); + if (context != null) + { + IUriContext iuc = (IUriContext)context.GetService(typeof(IUriContext)); + + //Debug.Assert (iuc != null, "IUriContext should not be null here"); + if (iuc != null) + { + // the base uri is NOT "" + if (iuc.BaseUri != null) + { + + uriHolder.BaseUri = iuc.BaseUri; + + if (!uriHolder.BaseUri.IsAbsoluteUri) + { + uriHolder.BaseUri = new Uri(BaseUriHelper.BaseUri, uriHolder.BaseUri); + } + } // uriHolder.BaseUriString != "" + else + { + // if we reach here, the base uri we got from IUriContext is "" + // and the inputString is a relative uri. Here we resolve it to + // application's base + uriHolder.BaseUri = BaseUriHelper.BaseUri; + } + } // iuc != null + } // context!= null + } // uriHolder.OriginalUri.IsAbsoluteUri == false + + return uriHolder; + } + } + +#endregion +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml.sln b/src/Microsoft.DotNet.Wpf/src/System.Xaml.sln new file mode 100644 index 00000000000..82659d181b3 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2048 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Xaml", "System.Xaml\System.Xaml.csproj", "{9AC36357-34B7-40A1-95CA-FE9F46D089A7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Debug|x64.ActiveCfg = Debug|x64 + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Debug|x64.Build.0 = Debug|x64 + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Debug|x86.ActiveCfg = Debug|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Debug|x86.Build.0 = Debug|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Release|Any CPU.Build.0 = Release|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Release|x64.ActiveCfg = Release|x64 + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Release|x64.Build.0 = Release|x64 + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Release|x86.ActiveCfg = Release|Any CPU + {9AC36357-34B7-40A1-95CA-FE9F46D089A7}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {671D19D1-5F0E-4453-9D18-3A28AC0E8DEF} + EndGlobalSection +EndGlobal diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/Configurations.props b/src/Microsoft.DotNet.Wpf/src/System.Xaml/Configurations.props new file mode 100644 index 00000000000..6cc4dcd0ebe --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/Configurations.props @@ -0,0 +1,8 @@ + + + + + netcoreapp-Windows_NT; + + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/Directory.Build.Props b/src/Microsoft.DotNet.Wpf/src/System.Xaml/Directory.Build.Props new file mode 100644 index 00000000000..c309ecaecb1 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/Directory.Build.Props @@ -0,0 +1,9 @@ + + + + + 4.0.0.0 + ECMA + true + + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/CodeQuality.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/CodeQuality.cs new file mode 100644 index 00000000000..e46f579164d --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/CodeQuality.cs @@ -0,0 +1,9 @@ +// +// FxCop Violation Message Suppressions +// Approved List +// + +using System.Diagnostics.CodeAnalysis; + +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope="member", Target="System.Xaml.Schema.SafeReflectionInvoker.#DemandMemberAccessPermission()", Justification="Retained per servicing policy.")] + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Globalization.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Globalization.cs new file mode 100644 index 00000000000..a9132995f2c --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Globalization.cs @@ -0,0 +1,9 @@ +// +// FxCop Violation Message Suppressions +// Approved List +// + +using System.Diagnostics.CodeAnalysis; + + + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Microsoft.Design.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Microsoft.Design.cs new file mode 100644 index 00000000000..1b7dbb45ec2 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Microsoft.Design.cs @@ -0,0 +1,5 @@ +using System.Diagnostics.CodeAnalysis; + +[module: SuppressMessage("Microsoft.Design","CA1028:EnumStorageShouldBeInt32", Scope="type", Target="System.Xaml.Schema.XamlCollectionKind", Justification="Our measurements showed this type provided improved spacial complexity.")] + +[module: SuppressMessage("Microsoft.Design","CA1028:EnumStorageShouldBeInt32", Scope="type", Target="System.Xaml.XamlNodeType", Justification="Our measurements showed this type provided improved spacial complexity.")] diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Microsoft.Naming.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Microsoft.Naming.cs new file mode 100644 index 00000000000..3cfa179152f --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Microsoft.Naming.cs @@ -0,0 +1,65 @@ +// +// FxCop Violation Message Suppressions +// Approved List +// + +using System.Diagnostics.CodeAnalysis; + +// Whitespace is consistent with WhitespaceSignificantCollectionAttribute from 3.0 +[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope="member", Target="System.Xaml.XamlType.#IsWhitespaceSignificantCollectionCore", MessageId="Whitespace", Justification="Add Whitespace to the dictionary if we already shipped, and it seems good.")] +[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope="member", Target="System.Xaml.XamlType.#IsWhitespaceSignificantCollection", MessageId="Whitespace", Justification="Add Whitespace to the dictionary if we already shipped, and it seems good.")] +[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope="member", Target="System.Xaml.XamlType.#TrimSurroundingWhitespace", MessageId="Whitespace", Justification="Add Whitespace to the dictionary if we already shipped, and it seems good.")] +[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope="member", Target="System.Xaml.XamlType.#TrimSurroundingWhitespaceCore", MessageId="Whitespace", Justification="Add Whitespace to the dictionary if we already shipped, and it seems good.")] +[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope="member", Target="System.Xaml.Schema.XaslType.#IsWhitespaceSignificantCollection", MessageId="Whitespace", Justification="Add Whitespace to the dictionary if we already shipped, and it seems good.")] +[module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope="member", Target="System.Xaml.Schema.XaslType.#TrimSurroundingWhitespace", MessageId="Whitespace", Justification="Add Whitespace to the dictionary if we already shipped, and it seems good.")] + +// use of Eof is an API choice. +[module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope = "member", Target = "System.Xaml.XamlReader.#IsEof", MessageId = "Eof", Justification = "Review Eof")] + +[module: SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope="type", Target="System.Xaml.XamlNodeQueue", Justification="This is unnecessarily limiting.")] + +[module: SuppressMessage("Microsoft.Naming","CA1721:PropertyNamesShouldNotMatchGetMethods", Scope="member", Target="System.Windows.Markup.PropertyDefinition.#Type", Justification="Makes sense for our problem domain.")] + +[module: SuppressMessage("Microsoft.Naming","CA1721:PropertyNamesShouldNotMatchGetMethods", Scope="member", Target="System.Xaml.XamlMember.#Type", Justification="Makes sense for our problem domain.")] + +[module: SuppressMessage("Microsoft.Naming","CA1721:PropertyNamesShouldNotMatchGetMethods", Scope="member", Target="System.Xaml.XamlReader.#Type", Justification="Makes sense for our problem domain.")] + +[module: SuppressMessage("Microsoft.Naming","CA1716:IdentifiersShouldNotMatchKeywords", Scope="member", Target="System.Xaml.XamlReader.#Namespace", MessageId="Namespace", Justification="Works for our problem domain.")] + +[module: SuppressMessage("Microsoft.Naming","CA1702:CompoundWordsShouldBeCasedCorrectly", Scope="member", Target="System.Xaml.XamlType.#LookupIsWhitespaceSignificantCollection()", MessageId="Whitespace", Justification="Back compat.")] + +[module: SuppressMessage("Microsoft.Naming","CA1702:CompoundWordsShouldBeCasedCorrectly", Scope="member", Target="System.Xaml.XamlType.#LookupTrimSurroundingWhitespace()", MessageId="Whitespace", Justification="Back compat.")] + +[module: SuppressMessage("Microsoft.Naming","CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId="SubClass", Scope="member", Target="System.Xaml.XamlLanguage.#SubClass", Justification="Needs to match the capitalization used in XAML syntax.")] + +[module: SuppressMessage("Microsoft.Naming","CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId="Whitespace", Scope="type", Target="System.Windows.Markup.TrimSurroundingWhitespaceAttribute", Justification="Kept for compatibility.")] + +[module: SuppressMessage("Microsoft.Naming","CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId="Whitespace", Scope="type", Target="System.Windows.Markup.WhitespaceSignificantCollectionAttribute", Justification="Kept for compatibility.")] + +[module: SuppressMessage("Microsoft.Naming","CA1721:PropertyNamesShouldNotMatchGetMethods", Scope="member", Target="System.Windows.Markup.ArrayExtension.#Type", Justification="Kept for compatibility.")] + +[module: SuppressMessage("Microsoft.Naming","CA1721:PropertyNamesShouldNotMatchGetMethods", Scope="member", Target="System.Windows.Markup.TypeExtension.#Type", Justification="Kept for compatibility.")] + +[module: SuppressMessage("Microsoft.Naming","CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId="nameSpace", Scope="member", Target="System.Windows.Markup.RootNamespaceAttribute.#.ctor(System.String)", Justification="Inherited from Base.")] + +[module: SuppressMessage("Microsoft.Naming","CA1721:PropertyNamesShouldNotMatchGetMethods", Scope="member", Target="System.Windows.Markup.NameScopePropertyAttribute.#Type", Justification="Kept for compatibility.")] + +// FrugalList suppressions copied over from WindowsBase +[module: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope="member", Target="System.Xaml.MS.Impl.ThreeItemList`1.Promote(System.Xaml.MS.Impl.ThreeItemList`1):System.Void")] +[module: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope="member", Target="System.Xaml.MS.Impl.ThreeItemList`1.SetCount(System.Int32):System.Void")] +[module: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope="member", Target="System.Xaml.MS.Impl.ThreeItemList`1.Promote(System.Xaml.MS.Impl.FrugalListBase`1):System.Void")] +[module: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope="member", Target="System.Xaml.MS.Impl.ArrayItemList`1.Promote(System.Xaml.MS.Impl.SixItemList`1):System.Void")] +[module: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope="member", Target="System.Xaml.MS.Impl.ArrayItemList`1.SetCount(System.Int32):System.Void")] +[module: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope="member", Target="System.Xaml.MS.Impl.SingleItemList`1.SetCount(System.Int32):System.Void")] +[module: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope="member", Target="System.Xaml.MS.Impl.SixItemList`1.Promote(System.Xaml.MS.Impl.SixItemList`1):System.Void")] +[module: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope="member", Target="System.Xaml.MS.Impl.SixItemList`1.Promote(System.Xaml.MS.Impl.ThreeItemList`1):System.Void")] +[module: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope="member", Target="System.Xaml.MS.Impl.SixItemList`1.SetCount(System.Int32):System.Void")] +[module: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope="member", Target="System.Xaml.MS.Impl.SixItemList`1.Promote(System.Xaml.MS.Impl.FrugalListBase`1):System.Void")] + +[module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Uid", Scope = "type", Target = "System.Windows.Markup.UidPropertyAttribute")] +[module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Uid", Scope = "member", Target = "System.Xaml.XamlLanguage.#Uid")] +[module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Namescope", Scope = "member", Target = "System.Xaml.XamlObjectWriterSettings.#RegisterNamesOnExternalNamescope")] +[module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Uids", Scope = "member", Target = "System.Xaml.XamlReaderSettings.#IgnoreUidsOnPropertyElements")] +[module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Arity", Scope = "member", Target = "System.Xaml.XamlSchemaContext.#SupportMarkupExtensionsWithDuplicateArity")] +[module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Arity", Scope = "member", Target = "System.Xaml.XamlSchemaContextSettings.#SupportMarkupExtensionsWithDuplicateArity")] +[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "Arity", Scope = "resource", Target = "ExceptionStringTable.resources")] diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Microsoft.Usage.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Microsoft.Usage.cs new file mode 100644 index 00000000000..b1c79bc8cf7 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Microsoft.Usage.cs @@ -0,0 +1,25 @@ +using System.Diagnostics.CodeAnalysis; + +//*************************************************************************************************************************** +// Ignoring the return is intentional in all of the cases below. Successful ETW registration isn’t critical for the app to continue running since it’s just for diagnostic purposes. +//*************************************************************************************************************************** +[module: SuppressMessage("Microsoft.Usage","CA1806:DoNotIgnoreMethodResults", MessageId="MS.Win32.ClassicEtw.UnregisterTraceGuids(System.UInt64)", Scope="member", Target="MS.Internal.Xaml.ClassicTraceProvider.#Finalize()")] +[module: SuppressMessage("Microsoft.Usage","CA1806:DoNotIgnoreMethodResults", MessageId="MS.Win32.ClassicEtw.RegisterTraceGuidsW(MS.Win32.ClassicEtw+ControlCallback,System.IntPtr,System.Guid@,System.Int32,MS.Win32.ClassicEtw+TRACE_GUID_REGISTRATION@,System.String,System.String,System.UInt64@)", Scope="member", Target="MS.Internal.Xaml.ClassicTraceProvider.#Register(System.Guid)")] +[module: SuppressMessage("Microsoft.Usage","CA1806:DoNotIgnoreMethodResults", MessageId="MS.Win32.ManifestEtw.EventUnregister(System.UInt64)", Scope="member", Target="MS.Internal.Xaml.ManifestTraceProvider.#Finalize()")] +[module: SuppressMessage("Microsoft.Usage","CA1806:DoNotIgnoreMethodResults", MessageId="MS.Win32.ManifestEtw.EventRegister(System.Guid@,MS.Win32.ManifestEtw+EtwEnableCallback,System.Void*,System.UInt64@)", Scope="member", Target="MS.Internal.Xaml.ManifestTraceProvider.#Register(System.Guid)")] + +[module: SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Xaml.GCNotificationToken", Scope = "member", Target = "System.Xaml.GCNotificationToken.#RegisterCallback(System.Threading.WaitCallback,System.Object)", Justification = "The GCNotificationToken object is created only for the executing code to be notified of a GC and is intended to be released immediately")] + +//*************************************************************************************************************************** +// Warnings related to the No Primary Interop Assembly (NoPIA) are suppressed. This is not relevant to WPF at the moment. +//*************************************************************************************************************************** +[module: SuppressMessage("Microsoft.Usage","CA2302:FlagServiceProviders", Scope="type", Target="MS.Internal.Xaml.ServiceProviderContext")] +[module: SuppressMessage("Microsoft.Usage","CA2301:EmbeddableTypesInContainersRule", MessageId="DelegateCreators", Scope="member", Target="MS.Internal.Xaml.Runtime.DynamicMethodRuntime.#CreateDelegate(System.Type,System.Object,System.String)")] +[module: SuppressMessage("Microsoft.Usage","CA2301:EmbeddableTypesInContainersRule", MessageId="ConverterInstances", Scope="member", Target="MS.Internal.Xaml.Runtime.DynamicMethodRuntime.#GetConverterInstance`1(System.Xaml.Schema.XamlValueConverter`1)")] +[module: SuppressMessage("Microsoft.Usage","CA2303:FlagTypeGetHashCode", Scope="member", Target="System.Windows.Markup.ContentWrapperAttribute.#GetHashCode()")] +[module: SuppressMessage("Microsoft.Usage","CA2302:FlagServiceProviders", Scope="type", Target="System.Windows.Markup.IValueSerializerContext")] +[module: SuppressMessage("Microsoft.Usage","CA2303:FlagTypeGetHashCode", Scope="member", Target="System.Xaml.AttachableMemberIdentifier.#GetHashCode()")] +[module: SuppressMessage("Microsoft.Usage","CA2302:FlagServiceProviders", Scope="type", Target="System.Xaml.XamlObjectReader+TypeDescriptorAndValueSerializerContext")] +[module: SuppressMessage("Microsoft.Usage","CA2303:FlagTypeGetHashCode", MessageId="get_UnderlyingType", Scope="member", Target="System.Xaml.XamlType.#GetHashCode()")] +[module: SuppressMessage("Microsoft.Usage","CA2302:FlagServiceProviders", Scope="type", Target="System.Xaml.Replacements.DateTimeValueSerializerContext")] +[module: SuppressMessage("Microsoft.Usage","CA2303:FlagTypeGetHashCode", MessageId="get_ConverterType", Scope="member", Target="System.Xaml.Schema.XamlValueConverter`1.#GetHashCode()")] diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Performance.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Performance.cs new file mode 100644 index 00000000000..a55fd1671b5 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Performance.cs @@ -0,0 +1,48 @@ +// +// FxCop Violation Message Suppressions +// Approved List +// + +using System.Diagnostics.CodeAnalysis; + +// This is used in a Stack and all the calls to "new" are "new T" +[module: SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Scope = "type", Target = "MS.Internal.Xaml.Context.ObjectWriterFrame")] + +// Need this public Ctor Override that takes an InnerExcepetion. +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Xaml.XamlParseException.#.ctor(MS.Internal.Xaml.Context.XamlParserContext,System.String,System.Exception)")] + +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.EventTrace.#EasyTraceEvent(MS.Internal.Xaml.EventTrace+Keyword,MS.Internal.Xaml.EventTrace+Event)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.EventTrace.#EasyTraceEvent(MS.Internal.Xaml.EventTrace+Keyword,MS.Internal.Xaml.EventTrace+Event,System.Object)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.EventTrace.#EasyTraceEvent(MS.Internal.Xaml.EventTrace+Keyword,MS.Internal.Xaml.EventTrace+Event,System.Object,System.Object)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.EventTrace.#EasyTraceEvent(MS.Internal.Xaml.EventTrace+Keyword,MS.Internal.Xaml.EventTrace+Event,System.Object,System.Object,System.Object)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.EventTrace.#EasyTraceEvent(MS.Internal.Xaml.EventTrace+Keyword,MS.Internal.Xaml.EventTrace+Level,MS.Internal.Xaml.EventTrace+Event)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.EventTrace.#EasyTraceEvent(MS.Internal.Xaml.EventTrace+Keyword,MS.Internal.Xaml.EventTrace+Level,MS.Internal.Xaml.EventTrace+Event,System.Object)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.EventTrace.#EasyTraceEvent(MS.Internal.Xaml.EventTrace+Keyword,MS.Internal.Xaml.EventTrace+Level,MS.Internal.Xaml.EventTrace+Event,System.Object,System.Object)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.TraceProvider.#get_Keywords()", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.TraceProvider.#get_Level()", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.TraceProvider.#get_MatchAllKeywords()", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.TraceProvider.#TraceEvent(MS.Internal.Xaml.EventTrace+Event,MS.Internal.Xaml.EventTrace+Keyword,MS.Internal.Xaml.EventTrace+Level)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.TraceProvider.#TraceEvent(MS.Internal.Xaml.EventTrace+Event,MS.Internal.Xaml.EventTrace+Keyword,MS.Internal.Xaml.EventTrace+Level,System.Object)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.Context.ObjectWriterContext.#get_ParentInstanceRegisteredName()", Justification = "We need the setter, and write-only properties are bad practice")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Internal.Xaml.Context.ObjectWriterContext.#get_ParentKey()", Justification = "We need the setter, and write-only properties are bad practice")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "MS.Win32.ClassicEtw.#GetTraceLoggerHandle(MS.Win32.ClassicEtw+WNODE_HEADER*)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Xaml.ReflectionHelper.#GetAlreadyLoadedAssembly(System.String)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Xaml.ReflectionHelper.#GetCustomAttributeData(System.Collections.Generic.IList`1,System.Type,System.Type&,System.Boolean,System.Boolean)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Xaml.ReflectionHelper.#GetCustomAttributeData(System.Reflection.MemberInfo,System.Type,System.Type&)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Xaml.ReflectionHelper.#GetTypeConverterAttributeData(System.Reflection.MemberInfo,System.Type&)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Xaml.ReflectionHelper.#IsInternalType(System.Type)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Xaml.ReflectionHelper.#ResetCacheForAssembly(System.String)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Xaml.SR.#get_ResourceManager()", Justification = "Auto-generated")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Xaml.XmlCompatibilityReader.#.ctor(System.Xml.XmlReader,System.Collections.Generic.IEnumerable`1)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Xaml.XmlCompatibilityReader.#.ctor(System.Xml.XmlReader,System.Xaml.IsXmlNamespaceSupportedCallback,System.Collections.Generic.IEnumerable`1)", Justification = "Shared source file")] +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Xaml.XmlCompatibilityReader.#get_Encoding()", Justification = "Shared source file")] + +// This is a debug-only method, we should mark it as Conditional("DEBUG") +[module: SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Xaml.XamlNode.#IsEof_Helper(System.Xaml.XamlNodeType,System.Object)", Justification = "Fix doesn't meet Ask Mode bar")] + +[module: SuppressMessage("Microsoft.Performance","CA1811:AvoidUncalledPrivateCode", Scope="member", Target="System.Xaml.XamlObjectWriter.#get_ObjectWriterContext()", Justification="Fix doesn't meet Ask Mode bar - Bug 773900")] + +// New since v4 RTM: + +//this is used by subclasses, bad FxCop detection +[module: SuppressMessage("Microsoft.Performance","CA1812:AvoidUninstantiatedInternalClasses", Scope="type", Target="System.Xaml.MS.Impl.FrugalObjectList`1+Compacter")] diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Reliability.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Reliability.cs new file mode 100644 index 00000000000..837de646fc6 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Reliability.cs @@ -0,0 +1,12 @@ +// +// FxCop Violation Message Suppressions +// Approved List +// + +using System.Diagnostics.CodeAnalysis; + +[module: SuppressMessage("Microsoft.Reliability","CA2001:AvoidCallingProblematicMethods", Scope="member", Target="System.Xaml.Schema.ClrNamespace.#ParseClrNamespaceUri(System.String)", MessageId="System.Reflection.Assembly.LoadWithPartialName", Justification="Back compat.")] + +[module: SuppressMessage("Microsoft.Reliability","CA2001:AvoidCallingProblematicMethods", MessageId="System.Reflection.Assembly.LoadFile", Scope="member", Target="System.Xaml.ReflectionHelper.#LoadAssemblyHelper(System.String,System.String)")] + +[module: SuppressMessage("Microsoft.Reliability","CA2001:AvoidCallingProblematicMethods", MessageId="System.Reflection.Assembly.LoadWithPartialName", Scope="member", Target="System.Xaml.XamlSchemaContext.#ResolveAssembly(System.String)", Justification="Need to support load of assemblies from GAC by short name.")] diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Security.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Security.cs new file mode 100644 index 00000000000..c2373499438 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Security.cs @@ -0,0 +1,19 @@ +// +// FxCop Violation Message Suppressions +// Approved List +// + +using System.Diagnostics.CodeAnalysis; + +// Begin + +[module: SuppressMessage("Microsoft.Security","CA2103:ReviewImperativeSecurity", Scope="member", Target="System.Xaml.Permissions.XamlLoadPermission.#Copy()", Justification="Reviewed by senior CLR security developer.")] + +[module: SuppressMessage("Microsoft.Security","CA2103:ReviewImperativeSecurity", Scope="member", Target="MS.Internal.Xaml.Runtime.DynamicMethodRuntime.#.ctor(MS.Internal.Xaml.Runtime.XamlRuntimeSettings,System.Xaml.XamlSchemaContext,System.Xaml.Permissions.XamlAccessLevel)", Justification="Reviewed by Microsoft.")] + +[module: SuppressMessage("Microsoft.Security","CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Scope="member", Target="System.Xaml.XamlObjectReader+ObjectMarkupInfo.#GetInstanceDescriptorInfo(System.ComponentModel.Design.Serialization.InstanceDescriptor,System.Reflection.MemberInfo&,System.Collections.ICollection&,System.Boolean&)", Justification="Non-issue since C# 2.0. LinkDemand is FullDemand by default without a SecurityCritical attribute.")] + +[module: SuppressMessage("Microsoft.Security","CA2106:SecureAsserts", Scope="member", Target="MS.Internal.Utility.PerfServiceProxy.#InitializeGetId()", Justification="Doesn't make sense with security transparency system. Reviewed by Microsoft")] + +// End + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Stability.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Stability.cs new file mode 100644 index 00000000000..1949251d0cd --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/FxCop/Xaml/Stability.cs @@ -0,0 +1,7 @@ +// +// FxCop Violation Message Suppressions +// Approved List +// + +using System.Diagnostics.CodeAnalysis; + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/Resources/ExceptionStringTable.txt b/src/Microsoft.DotNet.Wpf/src/System.Xaml/Resources/ExceptionStringTable.txt new file mode 100644 index 00000000000..4c83fa793f3 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/Resources/ExceptionStringTable.txt @@ -0,0 +1,417 @@ + +; +; US-EN Exception String Table +; Default Resource (used for English and non-represented locales) +; + + +; XmlCompatibilityReader +XCRChoiceOnlyInAC=Choice is valid only in AlternateContent. +XCRChoiceAfterFallback=Choice cannot follow a Fallback. +XCRRequiresAttribNotFound=Choice must contain a Requires attribute. +XCRInvalidRequiresAttribute=Requires attribute must contain a valid namespace prefix. +XCRFallbackOnlyInAC=Fallback is valid only in AlternateContent. +XCRChoiceNotFound=AlternateContent must contain one or more Choice elements. +XCRMultipleFallbackFound=AlternateContent must contain only one Fallback element. +XCRInvalidAttribInElement='{0}' attribute is not valid for '{1}' element. +XCRUnknownCompatElement=Unrecognized Compatibility element '{0}'. +XCRInvalidACChild='{0}' element is not a valid child of AlternateContent. Only Choice and Fallback elements are valid children of an AlternateContent element. +XCRInvalidFormat='{0}' format is not valid. +XCRUndefinedPrefix='{0}' prefix is not defined. +XCRUnknownCompatAttrib=Unrecognized compatibility attribute '{0}'. +XCRNSProcessContentNotIgnorable='{0}' namespace cannot process content; it must be declared Ignorable first. +XCRDuplicateProcessContent=Duplicate ProcessContent declaration for element '{1}' in namespace '{0}'. +XCRInvalidProcessContent=Cannot have both a specific and a wildcard ProcessContent declaration for namespace '{0}'. +XCRDuplicateWildcardProcessContent=Duplicate wildcard ProcessContent declaration for namespace '{0}'. +XCRMustUnderstandFailed=MustUnderstand condition failed on namespace '{0}'. +XCRNSPreserveNotIgnorable='{0}' namespace cannot preserve items; it must be declared Ignorable first. +XCRDuplicatePreserve=Duplicate Preserve declaration for element '{1}' in namespace '{0}'. +XCRInvalidPreserve=Cannot have both a specific and a wildcard Preserve declaration for namespace '{0}'. +XCRDuplicateWildcardPreserve=Duplicate wildcard Preserve declaration for namespace '{0}'. +XCRInvalidXMLName='{0}' attribute value is not a valid XML name. +XCRCompatCycle=There is a cycle of XML compatibility definitions, such that namespace '{0}' overrides itself. This could be due to inconsistent XmlnsCompatibilityAttributes in different assemblies. Please change the definitions to eliminate this cycle, or pass a non-conflicting set of Reference Assemblies in the XamlSchemaContext constructor. + +; XamlSystemBinding +BadXmlnsDefinition=An XmlnsDefinitionAttribute in assembly '{0}' is missing a required property. Set both the ClrNamespace and XmlNamespace properties, or remove the XmlnsDefinitionAttribute. +BadXmlnsCompat=An XmlnsCompatibleWithAttribute in assembly '{0}' is missing a required property. Set both the NewNamespace and OldNamespace properties, or remove the XmlnsCompatibleWithAttribute. +BadXmlnsPrefix=An XmlnsPrefixAttribute in assembly '{0}' is missing a required property. Set both the Prefix and XmlNamespace properties, or remove the XmlnsPrefixAttribute. +BadInternalsVisibleTo1=One of the InternalsVisibleToAttribute values in assembly '{0}' is not a valid assembly name. Use the format 'AssemblyShortName' or 'AssemblyShortName, PublicKey=...'. +BadInternalsVisibleTo2=InternalsVisibleToAttribute value '{0}' in assembly '{1}' is not a valid assembly name. Use the format 'AssemblyShortName' or 'AssemblyShortName, PublicKey=...'. +DuplicateXmlnsCompat=There is more than one XmlnsCompatibleWithAttribute in assembly '{0}' for OldNamespace '{1}'. Remove the extra attribute(s). +XmlnsCompatCycle=There is a cycle of XmlnsCompatibleWithAttribute definitions in assembly '{0}', such that namespace '{1}' overrides itself. Change the definitions to eliminate this cycle. +UriNotFound=Uri '{0}' was not found. +DuplicateXmlnsCompatAcrossAssemblies=There are conflicting XmlnsCompatibleWithAttributes in assemblies '{0}' and '{1}' for OldNamespace '{2}'. Change the attributes to have the same NewNamespace, or pass a non-conflicting set of Reference Assemblies in the XamlSchemaContext constructor. + +; ClrNamespace +UnresolvedNamespace=XAML namespace '{0}' is not resolved. +TypeNotFound=Type reference cannot find type named '{0}'. +TypeNotPublic=Type '{0}' is not public. +TooManyTypeConverterAttributes=Only one TypeConverter attribute is allowed on a type. +CannotFindAssembly=Cannot find Assembly '{0}' in URI '{1}'. +MissingAssemblyName=No local assembly provided to complete URI='{0}'. +InvalidTypeArgument=Type argument '{0}' is not a valid type. +FileNotFoundExceptionMessage=Could not load file or assembly '{0}' or one of its dependencies. The system cannot find the specified file. + +; XaslNamespace +DirectiveNotFound=Directive '{0}' was not found in TargetNamespace '{1}'. + +; Xaml +MustNotCallSetter=This setter is not intended to be used directly from your code. Do not call this setter. + +; XamlProperty +MissingLookPropertyBit=Missing case handler in LookupPropertyBit. +TooManyAttributes=Error with member '{0}'.'{1}'. It has more than one '{2}'. + +; XaslMember +GetTargetTypeOnNonAttachableMember=Cannot get TargetType on a non-attachable Member. +SetTargetTypeOnNonAttachableMember=Cannot set TargetType on a non-attachable Member. + +; XamlObjectWriter +InvalidExpression=Invalid expression: '{0}' +MissingKey=Missing key value on '{0}' object. +PropertyDoesNotTakeText='{0}' property on '{1}' does not allow you to specify text. +EventCannotBeAssigned='{0}' event cannot be assigned a value that is not assignable to '{1}'. +TypeConverterFailed=Failed to create a '{0}' from the text '{1}'. +CantCreateUnknownType=Cannot create unknown type '{0}'. +CantSetUnknownProperty=Cannot set unknown member '{0}'. +MissingImplicitProperty=Missing implicit property case. +BuilderStackNotEmptyOnClose=Builder Stack is not empty when end of XamlNode stream was reached. +CannotSetSchemaContext=Cannot set SchemaContext on ObjectWriter. +MissingImplicitPropertyTypeCase=Missing case for ImplicitPropertyType. +ConstructImplicitType=Failed attempting to create an Implicit Type with a constructor. +NonMEWithPositionalParameters=Type with positional parameters is not a markup extension. +PositionalParamsWrongLength=GetPositionalParameters returned the wrong length vector. +BadStateObjectWriter=Bad state in ObjectWriter. Non directive missing instance. +DuplicateMemberSet='{0}' property has already been set on '{1}'. +NotAmbientProperty='{0}'.'{1}' is not an ambient property. +NotAmbientType='{0}' is not an ambient type. +NoSuchConstructor=No constructor with '{0}' arguments for '{1}'. +UnresolvedForwardReferences=Unresolved reference '{0}'. +CantAssignRootInstance=Cannot assign root instance of type '{0}' to type '{1}'. +ForwardRefDirectives=Attempt to reference named object(s) '{0}' which have not yet been defined. Forward references, or references to objects that contain forward references, are not supported on directives other than Key. +TransitiveForwardRefDirectives=Object '{0}' assigned to directive '{1}' has properties which are references to named object(s) '{2}' which have not yet been defined. Forward references, or references to objects that contain forward references, are not supported inside object construction directives. +TypeHasNoContentProperty=Type '{0}' does not have a content property. Specify the name of the property to set, or add a ContentPropertyAttribute or TypeConverterAttribute on the type. +GetObjectNull=Collection property '{0}'.'{1}' is null. +NotAssignableFrom=The type '{0}' is not assignable from the type '{1}'. +NameScopeNameNotEmptyString=Name cannot be an empty string. +NameScopeNameNotFound=Name '{0}' was not found. +NameScopeDuplicateNamesNotAllowed=Cannot register duplicate name '{0}' in this scope. +NameScopeInvalidIdentifierName='{0}' name is not valid for identifier. +NameScopeException=Could not register named object. {0} +ObjectWriterTypeNotAllowed='{0}' blocked the use of type '{1}' in XAML. If you want to load this type, change '{0}'.GetXamlType to return a non-null value for this type, or pass a different value in the schemaContext parameter of the XamlObjectWriter constructor. +DirectiveNotAtRoot=Directive '{0}' is only allowed on the root object. Remove this directive or move it to the root of the document. +DirectiveMustBeString=Directive '{0}' must be a value of type string. Remove this directive or change it to a string value. +XClassMustMatchRootInstance=Specified class name '{0}' doesn't match actual root instance type '{1}'. Remove the Class directive or provide an instance via XamlObjectWriterSettings.RootObjectInstance. +SavedContextSchemaContextMismatch=schemaContext parameter cannot be different from savedContext.SchemaContext +SavedContextSchemaContextNull=savedContext.SchemaContext cannot be null +SettingPropertiesIsNotAllowed=Setting properties is not allowed on a type converted instance. Property = '{0}' +LateConstructionDirective=Construction directive '{0}' must be an attribute or the first property element. +ProvideValueCycle=Cannot call MarkupExtension.ProvideValue because of a cyclical dependency. Properties inside a MarkupExtension cannot reference objects that reference the result of the MarkupExtension. The affected MarkupExtensions are: +AttachedPropOnFwdRefTC=Cannot set property '{0}' on object '{1}' because the object is a forward or incompletely initialized reference. The unresolved name(s) are: '{2}'. +InitializationSyntaxWithoutTypeConverter=Type '{0}' cannot be initialized from text (XamlLanguage.Initialization). Add a TypeConverter to this type or change the XAML to use a constructor or factory method. +NoPropertyInCurrentFrame_SO=XAML Node Stream: StartObject '{0}' requires a StartMember after StartObject '{1}'. +NoPropertyInCurrentFrame_NS=XAML Node Stream: '{0}'='{1}' Namespace Declaration requires a StartMember after StartObject '{2}'. +NoPropertyInCurrentFrame_GO=XAML Node Stream: GetObject requires a StartMember after StartObject '{0}'. +NoPropertyInCurrentFrame_GO_noType=XAML Node Stream: GetObject must follow a StartObject and StartMember. +NoPropertyInCurrentFrame_V=XAML Node Stream: Value of '{0}' requires a StartMember after StartObject '{1}'. +NoPropertyInCurrentFrame_V_noType=XAML Node Stream: Value of '{0}' must follow a StartObject and StartMember. +OpenPropertyInCurrentFrame_EO=XAML Node Stream: Missing EndMember for '{0}.{1}' before EndObject. +OpenPropertyInCurrentFrame_SM=XAML Node Stream: Missing EndMember for '{0}.{1}' before StartMember '{2}'. +NoTypeInCurrentFrame_SM=XAML Node Stream: Missing StartObject before StartMember '{0}'. +NoTypeInCurrentFrame_EO=XAML Node Stream: Missing CurrentObject before EndObject. +NoPropertyInCurrentFrame_EM=XAML Node Stream: Missing StartMember on Type '{0}' before EndMember. +NoPropertyInCurrentFrame_EM_noType=XAML Node Stream: EndMember must follow StartObject and StartMember. +ValueMustBeFollowedByEndMember=XAML Node Stream: Value nodes must be followed by EndMember. +DictionaryFirstChanceException=Dictionary of type '{0}' cannot add key '{1}'. A TypeConverter will convert the key to type '{2}'. To avoid seeing this error, override System.Collections.IDictionary.Add and perform the conversion there. +CannotSetBaseUri=BaseUri can only be set once at the root node (XamlXmlReader may provide a default at the root node). + +; DeferringWriter +DependsOnMissing='{0}'.'{1}' Depends on '{0}'.{1}', which was not set. +CloseInsideTemplate=Close called while inside a deferred load section. +UnexpectedClose=Unexpected close of XAML Node Stream. +TemplateNotCollected=Deferred load section was not collected in '{0}'. +DeferredPropertyNotCollected=Deferred member was not collected in '{0}'. +MissingCase=Missing case '{0}' in DeferringWriter'{1}' method. + +; ObjectWriterContext +NamespaceNotFound=Namespace '{0}' was not found in scope. +NameScopeOnRootInstance=Cannot attach NameScope to null root instance. +MissingNameResolver=Service provider is missing the INameResolver service. +ObjectNotTcOrMe=Argument should be a Type Converter, Markup Extension or Null. +SimpleFixupsMustHaveOneName=Directly Assignable Fixups must only have one name. + +; MePullParser +UnexpectedTokenAfterME=Unexpected token after end of markup extension. +WhitespaceAfterME=White space is not allowed after end of markup extension. +UnexpectedToken=Unexpected token '{0}' in rule: '{1}', in '{2}'. +NoConstructorWithNArugments=A Constructor for '{0}' with '{1}' arguments was not found. +MissingComma1=Unexpected equals sign '=' following '{0}'. Check for a missing comma separator. +MissingComma2=Unexpected equals sign '=' following '{0}'='{1}'. Check for a missing comma separator. + +; XamlName +TypeNameCannotHavePeriod=Type name '{0}' cannot have a dot '.'. + +; XamlPullParser +UnexpectedNodeType=Unexpected '{0}' in parse rule '{1}'. +ElementRuleException=Element ::= . EmptyElement | ( StartElement ElementBody ). +EmptyElementRuleException=EmptyElement ::= . EMPTYELEMENT DIRECTIVE* ATTRIBUTE*. +EmptyPropertyElementRuleException=EmptyPropertyElement ::= EMPTYPROPERTYELEMENT. +StartElementRuleException=StartElement ::= . ELEMENT DIRECTIVE*. +ElementBodyRuleException=ElementBody ::= ATTRIBUTE* ( PropertyElement | Content )* . ENDTAG. +NonemptyPropertyElementRuleException=NonemptyPropertyElement ::= . PROPERTYELEMENT Content? ENDTAG. +PropertyElementRuleException=PropertyElement ::= EmptyPropertyElement | NonemptyPropertyElement + + +; ClrNamespaceUriParser +MissingTagInNamespace=Missing '{0}' in URI '{1}'. +AssemblyTagMissing=Part between semicolon ';' and equals sign '=' is not '{0}' URI '{1}'. + +; TypeReflector +UnknownAttributeProperty=['{0}'('{1}')] on '{2}' is not a known property. +NotDeclaringTypeAttributeProperty=['{0}'('{1}')] on '{2}' is not a property declared on this type. +UsableDuringInitializationOnME=Error with type '{0}'. MarkupExtensions cannot use the 'UsableDuringInitialization' attribute. +TooManyAttributesOnType=Error with type '{0}'. It has more than one '{1}'. +MissingPropertyCaseClrType=Missing case in ClrType 'Member' lookup. +UnhandledBoolTypeBit=Unhandled BoolTypeBit. +AmbiguousCollectionItemType=Cannot determine the item type of collection type '{0}' because it has more than one Add method or ICollection implementation. To make this collection type usable in XAML, add a public Add(object) method, implement System.Collections.IList or a single System.Collections.Generic.ICollection. +AmbiguousDictionaryItemType=Cannot determine the item type of dictionary type '{0}' because it has more than one Add method or IDictionary implementation. To make this dictionary type usable in XAML, add a public Add(object,object) method, implement System.Collections.IDictionary or a single System.Collections.Generic.IDictionary. +MarkupExtensionWithDuplicateArity=Cannot determine the positional parameters for type '{0}' because it has more than one constructor overload with '{1}' parameters. To make this markup extension usable in XAML, remove the duplicate constructor overload(s) or set XamlSchemaContextSettings.SupportMarkupExtensionsWithDuplicateArity to true. + +; ClrProperty +SetOnlyProperty='{0}'.'{1}' is a property without a getter and is not a valid XAML property. + + +; XaslType +XaslTypePropertiesNotImplemented=Need to implement public/internal sorting. +AttachableMemberNotFound=Attachable member '{0}' was not found. +PropertyNotImplemented='{0}' is not implemented. + +; XamlContext +PrefixNotFound=Prefix '{0}' does not map to a namespace. + +; XamlException +LineNumberAndPosition='{0}' Line number '{1}' and line position '{2}'. +LineNumberOnly='{0}' Line number '{1}'. + +; MeScanner +QuoteCharactersOutOfPlace=Quote characters ' or " are only allowed at the start of values. +UnclosedQuote=Unclosed quoted value. +MalformedPropertyName=Cannot parse the malformed property name '{0}'. + +; XamlScanner +AttributeUnhandledKind=An unhandled scanner attribute was encountered. +UnknownType=Unknown type '{0}'. +UnknownMember=Unknown member '{0}' on '{1}'. +UnknownMemberSimple=Unknown member '{0}'. +UnknownMemberOnUnknownType=Unknown member '{0}' on unknown type '{1}'. +MemberIsInternal=Member '{0}' on type '{1}' is internal. +NoAttributeUsage='{0}' is not allowed in attribute usage. +NoElementUsage='{0}' is not allowed in element usage. +InvalidXamlMemberName='{0}' is not a valid XAML member name. +ParentlessPropertyElement=The property element '{0}' is not contained by an object element. + +; XamlBackgroundReader +SchemaContextNotInitialized=SchemaContext on writer must be initialized before accessing the reader. +ThreadAlreadyStarted=Thread is already started. + +; ReaderBaseDelegate +SchemaContextNull=SchemaContext cannot be null. + +; XamlNodeList +CloseXamlWriterBeforeReading=Must close XamlWriter before reading from XamlNodeList. +CannotWriteClosedWriter=Cannot write on a closed XamlWriter. +WriterIsClosed=An attempt was made to write to a XamlWriter that has had its Closed method called. + +; ClrObjectRuntime +DirectiveGetter=Directive getter is not implemented. +BadMethod=Bad method '{0}' on '{1}'. +CannotResolveTypeForFactoryMethod=Cannot resolve type '{0}' for method '{1}'. +CannotCreateBadType=Cannot create an instance of '{0}' because XamlType is not valid. +CannotCreateBadEventDelegate=Cannot create an instance of '{0}' because XamlType is not valid. +AttachableEventNotImplemented=Attachable events are not implemented. +ListNotIList=List collection is not an IList. +ArrayAddNotImplemented=Array Add method is not implemented. +NoAddMethodFound=No Add methods found on type '{0}' for a value of type '{1}'. +MissingTypeConverter=Creating from text without a TypeConverter is not allowed. +CantSetReadonlyProperty=Cannot set read-only property '{0}'. +CantGetWriteonlyProperty=Cannot get write-only property '{0}'. +XmlDataNull=The value for XmlData property '{0}' is null or not IXmlSerializable. +XmlValueNotReader=The value for XmlData property '{0}' is not an XmlReader. +NameNotFound=Name resolution failure. '{0}' was not found. +MustHaveName=Reference must have a Name to resolve. +MethodInvocation=The invocation of a method '{0}' that matches the specified binding constraints threw an exception. +GetValue=Get property '{0}' threw an exception. +SetValue=Set property '{0}' threw an exception. +AddCollection=Add value to collection of type '{0}' threw an exception. +AddDictionary=Add value to dictionary of type '{0}' threw an exception. +SetConnectionId=Set connectionId threw an exception. +InitializationGuard=Initialization of '{0}' threw an exception. +SetUriBase=Setting xml:base on '{0}' threw an exception. +ProvideValue=Provide value on '{0}' threw an exception. +SetXmlInstance=Setting xml instance on '{0}' threw an exception. +GetConverterInstance=Getting instance of '{0}' threw an exception. +DeferredLoad=Deferred load threw an exception. +DeferredSave=Save of deferred-load content threw an exception. +FactoryReturnedNull=The factory method '{0}' that matches the specified binding constraints returned null. +ConstructorInvocation=The invocation of the constructor on type '{0}' that matches the specified binding constraints threw an exception. +NoDefaultConstructor=No default constructor found for type '{0}'. You can use the Arguments or FactoryMethod directives to construct this type. +NoConstructor=No matching constructor found on type '{0}'. You can use the Arguments or FactoryMethod directives to construct this type. +DeferringLoaderInstanceNull=Cannot get a XamlDeferringLoader from XamlValueConverter '{0}' because its ConverterInstance property is null. +TypeConverterFailed2=Failed to convert '{0}' to type '{1}'. +CanConvertFromFailed=Failed to check convertibility from type '{0}' using '{1}'. This generally indicates an incorrectly implemented TypeConverter. +CanConvertToFailed=Failed to check convertibility to type '{0}' using '{1}'. This generally indicates an incorrectly implemented TypeConverter. +ShouldSerializeFailed=ShouldSerialize check failed for member '{0}'. +GetItemsReturnedNull=XamlTypeInvoker.GetItems returned null for type '{0}'. This generally indicates an incorrectly implemented collection type. +GetItemsException=Retrieving items in collection or dictionary of type '{0}' threw an exception. +APSException=Enumerating attached properties on object '{0}' threw an exception. + +; XamlWriter +CannotReassignSchemaContext=Cannot reassign a previously set SchemaContext. +CannotSetSchemaContextNull=Cannot set SchemaContext to null. +MissingCaseXamlNodes=Missing case in Default processing of XamlNodes. + +; TypeExension +MarkupExtensionTypeName=TypeExtension must have TypeName property set before ProvideValue can be called. +MarkupExtensionTypeNameBad='{0}' string is not valid for type. +MarkupExtensionNoContext=Markup extension '{0}' requires '{1}' be implemented in the IServiceProvider for ProvideValue. + +; XamlXmlWriter +XamlXmlWriterWriteNotSupportedInCurrentState=Unable to call '{0}' in current state. +XamlXmlWriterWriteObjectNotSupportedInCurrentState=Unable to call WriteObject with isObjectFromMember set to true in current state. +XamlXmlWriterPrefixAlreadyDefinedInCurrentScope=The prefix '{0}' is already defined in current scope. +XamlXmlWriterNamespaceAlreadyHasPrefixInCurrentScope=Namespace '{0}' already has a prefix defined in current scope. +XamlXmlWriterDuplicateMember=The member '{0}' has already been written. +XamlXmlWriterIsObjectFromMemberSetForArraysOrNonCollections=The argument isObjectFromMember can only be set to true when the type is a collection. +XamlXmlWriterCannotWriteNonstringValue=Cannot write a value that is not a string. +ExpandPositionalParametersinTypeWithNoDefaultConstructor=Cannot write positional parameters in the current state. The writer cannot write the positional parameters in attribute form because the writer has started to write elements, nor can the writer expand the positional parameters due to the lack of a default constructor on the markup extension that contains the positional parameters. Try moving the positional parameter member earlier in the node stream, to a place where XamlXmlWriter can still write attributes. +ConstructorNotFoundForGivenPositionalParameters=Cannot write the given positional parameters because a matching constructor was not found. +ExpandPositionalParametersWithReadOnlyProperties=Cannot write positional parameters in the current state. The writer cannot write the positional parameters in attribute form because the writer has started to write elements, nor can the writer expand the positional parameters since not all properties are writable. Try moving the positional parameter member earlier in the node stream, to a place where XamlXmlWriter can still write attributes. +TypeHasInvalidXamlName=The name of the type '{0}' contains characters that are invalid in XAML. +MemberHasInvalidXamlName=The name of the member '{0}' contains characters that are invalid in XAML. +NamespaceDeclarationCannotBeXml=The prefix 'xml' is reserved. +ExpandPositionalParametersWithoutUnderlyingType=Cannot write positional parameters in the current state. The writer cannot write the positional parameters in attribute form because the writer has started to write elements, nor can the writer expand the positional parameters since UnderlyingType on type '{0}' is null. Try moving the positional parameter member earlier in the node stream, to place where XamlXmlWriter can still write attributes. +PrefixNotInFrames=The prefix '{0}' could not be found. +WhiteSpaceInCollection=XamlXmlWriter cannot write value '{0}' which contains significant white space in collection '{1}'. +CannotWriteXmlSpacePreserveOnMember=The value '{1}' contains significant white space(s) but "xml:space = preserve" cannot be written down on the member '{0}'. + +; XamlTypeName +InvalidTypeString=The string '{0}' is not a valid XAML type name. Type names contain an optional prefix, a name, and optional type arguments; such as 'String', 'x:Int32', 'g:Dictionary(x:String,x:Int32)'. +InvalidTypeListString=The string '{0}' is not a valid XAML type name list. Type name lists are comma-delimited lists of types; such as 'x:String, x:Int32'. +InvalidCharInTypeName=Character '{0}' was unexpected in string '{1}'. Invalid XAML type name. +XamlTypeNameNamespaceIsNull=Cannot convert this XamlTypeName instance to a string because the Namespace property is null. Set the Namespace property before calling XamlTypeName.ToString. +XamlTypeNameNameIsNullOrEmpty=Cannot convert this XamlTypeName instance to a string because the Name property is null or empty. Set the Name property before calling XamlTypeName.ToString. +XamlTypeNameCannotGetPrefix=Cannot convert this XamlTypeName instance to a string because the provided INamespacePrefixLookup could not generate a prefix for the namespace '{0}'. + +; General +CollectionCannotContainNulls=Collection '{0}' cannot contain null values. + +; NamespaceDeclaration +NamespaceDeclarationPrefixCannotBeNull=NamespaceDeclaration.Prefix cannot be null. Provide a value for this property. +NamespaceDeclarationNamespaceCannotBeNull=NamespaceDeclaration.Namespace cannot be null. Provide a value for this property. + +; ClrAttachedProperty +IncorrectGetterParamNum=Attached property getter methods must have one parameter and a non-void return type. +IncorrectSetterParamNum=Attached property setter and attached event adder methods must have two parameters. +GetterOrSetterRequired=Either getter or setter must be non-null. + +; ObjectReader +ObjectReaderDictionaryMethod1NotFound=Unable to locate MemberMarkupInfo.DictionaryEntriesFromGeneric method. +ObjectReaderXamlNamedElementAlreadyRegistered=An element with the name '{0}' has already been registered in this scope. +ObjectReaderXamlNameScopeResultsInClonedObject=The object graph contains multiple references to an instance of type '{0}' and the serializer cannot find a commonly visible location to write the instance. You should examine your use of name scopes. +ObjectReaderXamlNamePropertyMustBeString=The name property '{0}' on type '{1}' must be of type System.String. +ObjectReaderNoDefaultConstructor=Unable to serialize type '{0}'. Verify that the type is public and either has a default constructor or an instance descriptor. +ObjectReaderNoMatchingConstructor=Unable to find a suitable constructor for the specified constructor arguments on type '{0}'. +ObjectReaderInstanceDescriptorIncompatibleArgumentTypes=InstanceDescriptor provided an argument of type '{0}' where a parameter of type '{1}' was expected. +ObjectReaderInstanceDescriptorIncompatibleArguments=InstanceDescriptor did not provide the correct number of arguments. +ObjectReaderInstanceDescriptorInvalidMethod=InstanceDescriptor did not provide a valid constructor or method. +ObjectReaderTypeCannotRoundtrip=Unable to read objects of the type ‘{0}’ because there are no accessible constructors. To allow this type to be used in XAML, add a default constructor, use ConstructorArgumentAttribute, or provide an InstanceDescriptor. +ObjectReaderTypeIsNested=Unable to read objects of the type '{0}'. Nested types are not supported. +ObjectReaderAttachedPropertyNotFound=Unable to find an attachable property named '{0}' on type '{1}'. +XamlFactoryInvalidXamlNode=Unexpected XAML node type '{0}' from XamlReader in XamlFactory. +CannotAddPositionalParameters=In markup extensions, all constructor argument values should be atoms. For the object of type '{0}', one or more argument values are not atomic. +ObjectReaderMultidimensionalArrayNotSupported=Multidimensional arrays not supported. +ObjectReaderTypeNotAllowed='{0}' blocked the use of type '{1}' in XAML. If you want to serialize this type, change '{0}'.GetXamlType to return a non-null value for this type, or pass a different value in the schemaContext parameter of the XamlObjectReader constructor. +ObjectReader_TypeNotVisible=Type '{0}' not visible. If the type is local, please set the LocalAssembly field in XamlReaderSettings. +ExpectedObjectMarkupInfo=Expected value of type ObjectMarkupInfo. +AttachedPropertyOnTypeConvertedOrStringProperty=An attachable property named '{2}' is attached to a property named '{1}'. The property named '{1}' is either a string or can be type-converted to string; attaching on such properties are not supported. For debugging, the property '{1}' contains an object '{0}'. +AttachedPropertyOnDictionaryKey=An attachable property named '{1}' is attached on a dictionary key '{0}' that is either a string or can be type-converted to string, which is not supported. +MissingNameProvider=Service provider is missing the IXamlNameProvider service. + +; XamlMarkupExtensionWriter +XamlMarkupExtensionWriterCannotSetSchemaContext=Cannot set SchemaContext on XamlMarkupExtensionWriter. +XamlMarkupExtensionWriterDuplicateMember=The member '{0}' has already been written. +XamlMarkupExtensionWriterCannotWriteNonstringValue=Cannot write a value that is not a string. +XamlMarkupExtensionWriterInputInvalid=Errors detected in input. + +; AttachablePropertyStore +DefaultAttachablePropertyStoreCannotAddInstance=Failed to add attached properties to item in ConditionalWeakTable. + +; AttributeReflector +UnexpectedConstructorArg=Invalid metadata for attribute '{0}' on '{1}'. Expected '{2}' argument(s) of type '{3}'. + +; XamlDeferringLoader +ShouldOverrideMethod=Method '{0}' is not supported by default. It can be implemented in derived classes. + +; XamlAccessLevel +ExpectedQualifiedTypeName=Type name '{0}' is not assembly-qualified. You can obtain this value from System.Type.AssemblyQualifiedName. +ExpectedQualifiedAssemblyName=Assembly name '{0}' is not fully qualified. The Name, Version, Culture, and PublicKeyToken must all be provided. + +; XamlLoadPermission +ExpectedLoadPermission=Expected permission of type XamlLoadPermission. +SecurityXmlUnexpectedTag=Invalid security XML. Unexpected tag '{0}', expected '{1}'. +SecurityXmlUnexpectedValue=Invalid security XML. Unexpected value '{0}' in attribute '{1}', expected '{2}'. +SecurityXmlMissingAttribute=Invalid security XML. Missing expected attribute '{0}'. + +; XamlServices +StringIsNullOrEmpty=The string is null or empty. + +; XamlTypeInvoker +NotSupportedOnUnknownType=This operation is not supported on unknown types. +OnlySupportedOnCollections=This operation is only supported on collection types. +OnlySupportedOnDictionaries=This operation is only supported on dictionary types. +OnlySupportedOnCollectionsAndDictionaries=This operation is only supported on collection and dictionary types. + +; XamlMemberInvoker +NotSupportedOnUnknownMember=This operation is not supported on unknown members. +NotSupportedOnDirective=This operation is not supported on directive members. + +; XamlValueConverter +ArgumentRequired=One of the following arguments must be non-null: '{0}'. +ConverterMustDeriveFromBase=Converter type '{0}' doesn't derive from expected base type '{1}'. + +; XamlSchemaContext +ReferenceIsNull=Value cannot be null. Object reference: '{0}'. + + +; Markup Extensions +MarkupExtensionArrayType=Must set Type before calling ProvideValue on ArrayExtension. +MarkupExtensionArrayBadType=Items in the array must be type '{0}'. One or more items cannot be cast to this type. +MarkupExtensionBadStatic='{0}' StaticExtension value cannot be resolved to an enumeration, static field, or static property. +MarkupExtensionStaticMember=StaticExtension must have Member property set before ProvideValue can be called. +MustBeOfType='{0}' must be of type '{1}'. + +;System.Windows.Markup +ToStringNull=(null) +ConvertToException='{0}' ValueSerializer cannot convert '{1}' to '{2}'. +ConvertFromException='{0}' ValueSerializer cannot convert from '{1}'. + +;System.Windows.Markup +ServiceTypeAlreadyAdded=This serviceType is already registered to another service. +QualifiedNameHasWrongFormat='{0}' type name does not have the expected format 'className, assembly'. +ParserAttributeArgsHigh=Too many attributes are specified for '{0}'. +ParserAttributeArgsLow='{0}' requires more attributes. +ParserAssemblyLoadVersionMismatch=Cannot load assembly '{0}' because a different version of that same assembly is loaded '{1}'. + +; FrugalList +FrugalList_TargetMapCannotHoldAllData=Cannot promote from '{0}' to '{1}' because the target map is too small. +FrugalList_CannotPromoteBeyondArray=Cannot promote from Array. + +; ServiceProviderContext +ValueInArrayIsNull=A value in the '{0}' array is null. + +; EventTrace +InvalidEvent=Event argument is invalid. + +; MarkupExtensionBracketCharacters +InvalidClosingBracketCharacers=Encountered a closing BracketCharacter '{0}' without a corresponding opening BracketCharacter. +MalformedBracketCharacters=BracketCharacter '{0}' does not have a corresponding opening/closing BracketCharacter. \ No newline at end of file diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/Resources/Strings.resx b/src/Microsoft.DotNet.Wpf/src/System.Xaml/Resources/Strings.resx new file mode 100644 index 00000000000..8c5993a9f17 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/Resources/Strings.resx @@ -0,0 +1,1038 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Choice is valid only in AlternateContent. + + + Choice cannot follow a Fallback. + + + Choice must contain a Requires attribute. + + + Requires attribute must contain a valid namespace prefix. + + + Fallback is valid only in AlternateContent. + + + AlternateContent must contain one or more Choice elements. + + + AlternateContent must contain only one Fallback element. + + + '{0}' attribute is not valid for '{1}' element. + + + Unrecognized Compatibility element '{0}'. + + + '{0}' element is not a valid child of AlternateContent. Only Choice and Fallback elements are valid children of an AlternateContent element. + + + '{0}' format is not valid. + + + '{0}' prefix is not defined. + + + Unrecognized compatibility attribute '{0}'. + + + '{0}' namespace cannot process content; it must be declared Ignorable first. + + + Duplicate ProcessContent declaration for element '{1}' in namespace '{0}'. + + + Cannot have both a specific and a wildcard ProcessContent declaration for namespace '{0}'. + + + Duplicate wildcard ProcessContent declaration for namespace '{0}'. + + + MustUnderstand condition failed on namespace '{0}'. + + + '{0}' namespace cannot preserve items; it must be declared Ignorable first. + + + Duplicate Preserve declaration for element '{1}' in namespace '{0}'. + + + Cannot have both a specific and a wildcard Preserve declaration for namespace '{0}'. + + + Duplicate wildcard Preserve declaration for namespace '{0}'. + + + '{0}' attribute value is not a valid XML name. + + + There is a cycle of XML compatibility definitions, such that namespace '{0}' overrides itself. This could be due to inconsistent XmlnsCompatibilityAttributes in different assemblies. Please change the definitions to eliminate this cycle, or pass a non-conflicting set of Reference Assemblies in the XamlSchemaContext constructor. + + + An XmlnsDefinitionAttribute in assembly '{0}' is missing a required property. Set both the ClrNamespace and XmlNamespace properties, or remove the XmlnsDefinitionAttribute. + + + An XmlnsCompatibleWithAttribute in assembly '{0}' is missing a required property. Set both the NewNamespace and OldNamespace properties, or remove the XmlnsCompatibleWithAttribute. + + + An XmlnsPrefixAttribute in assembly '{0}' is missing a required property. Set both the Prefix and XmlNamespace properties, or remove the XmlnsPrefixAttribute. + + + One of the InternalsVisibleToAttribute values in assembly '{0}' is not a valid assembly name. Use the format 'AssemblyShortName' or 'AssemblyShortName, PublicKey=...'. + + + InternalsVisibleToAttribute value '{0}' in assembly '{1}' is not a valid assembly name. Use the format 'AssemblyShortName' or 'AssemblyShortName, PublicKey=...'. + + + There is more than one XmlnsCompatibleWithAttribute in assembly '{0}' for OldNamespace '{1}'. Remove the extra attribute(s). + + + There is a cycle of XmlnsCompatibleWithAttribute definitions in assembly '{0}', such that namespace '{1}' overrides itself. Change the definitions to eliminate this cycle. + + + Uri '{0}' was not found. + + + There are conflicting XmlnsCompatibleWithAttributes in assemblies '{0}' and '{1}' for OldNamespace '{2}'. Change the attributes to have the same NewNamespace, or pass a non-conflicting set of Reference Assemblies in the XamlSchemaContext constructor. + + + XAML namespace '{0}' is not resolved. + + + Type reference cannot find type named '{0}'. + + + Type '{0}' is not public. + + + Only one TypeConverter attribute is allowed on a type. + + + Cannot find Assembly '{0}' in URI '{1}'. + + + No local assembly provided to complete URI='{0}'. + + + Type argument '{0}' is not a valid type. + + + Could not load file or assembly '{0}' or one of its dependencies. The system cannot find the specified file. + + + Directive '{0}' was not found in TargetNamespace '{1}'. + + + This setter is not intended to be used directly from your code. Do not call this setter. + + + Missing case handler in LookupPropertyBit. + + + Error with member '{0}'.'{1}'. It has more than one '{2}'. + + + Cannot get TargetType on a non-attachable Member. + + + Cannot set TargetType on a non-attachable Member. + + + Invalid expression: '{0}' + + + Missing key value on '{0}' object. + + + '{0}' property on '{1}' does not allow you to specify text. + + + '{0}' event cannot be assigned a value that is not assignable to '{1}'. + + + Failed to create a '{0}' from the text '{1}'. + + + Cannot create unknown type '{0}'. + + + Cannot set unknown member '{0}'. + + + Missing implicit property case. + + + Builder Stack is not empty when end of XamlNode stream was reached. + + + Cannot set SchemaContext on ObjectWriter. + + + Missing case for ImplicitPropertyType. + + + Failed attempting to create an Implicit Type with a constructor. + + + Type with positional parameters is not a markup extension. + + + GetPositionalParameters returned the wrong length vector. + + + Bad state in ObjectWriter. Non directive missing instance. + + + '{0}' property has already been set on '{1}'. + + + '{0}'.'{1}' is not an ambient property. + + + '{0}' is not an ambient type. + + + No constructor with '{0}' arguments for '{1}'. + + + Unresolved reference '{0}'. + + + Cannot assign root instance of type '{0}' to type '{1}'. + + + Attempt to reference named object(s) '{0}' which have not yet been defined. Forward references, or references to objects that contain forward references, are not supported on directives other than Key. + + + Object '{0}' assigned to directive '{1}' has properties which are references to named object(s) '{2}' which have not yet been defined. Forward references, or references to objects that contain forward references, are not supported inside object construction directives. + + + Type '{0}' does not have a content property. Specify the name of the property to set, or add a ContentPropertyAttribute or TypeConverterAttribute on the type. + + + Collection property '{0}'.'{1}' is null. + + + The type '{0}' is not assignable from the type '{1}'. + + + Name cannot be an empty string. + + + Name '{0}' was not found. + + + Cannot register duplicate name '{0}' in this scope. + + + '{0}' name is not valid for identifier. + + + Could not register named object. {0} + + + '{0}' blocked the use of type '{1}' in XAML. If you want to load this type, change '{0}'.GetXamlType to return a non-null value for this type, or pass a different value in the schemaContext parameter of the XamlObjectWriter constructor. + + + Directive '{0}' is only allowed on the root object. Remove this directive or move it to the root of the document. + + + Directive '{0}' must be a value of type string. Remove this directive or change it to a string value. + + + Specified class name '{0}' doesn't match actual root instance type '{1}'. Remove the Class directive or provide an instance via XamlObjectWriterSettings.RootObjectInstance. + + + schemaContext parameter cannot be different from savedContext.SchemaContext + + + savedContext.SchemaContext cannot be null + + + Setting properties is not allowed on a type converted instance. Property = '{0}' + + + Construction directive '{0}' must be an attribute or the first property element. + + + Cannot call MarkupExtension.ProvideValue because of a cyclical dependency. Properties inside a MarkupExtension cannot reference objects that reference the result of the MarkupExtension. The affected MarkupExtensions are: + + + Cannot set property '{0}' on object '{1}' because the object is a forward or incompletely initialized reference. The unresolved name(s) are: '{2}'. + + + Type '{0}' cannot be initialized from text (XamlLanguage.Initialization). Add a TypeConverter to this type or change the XAML to use a constructor or factory method. + + + XAML Node Stream: StartObject '{0}' requires a StartMember after StartObject '{1}'. + + + XAML Node Stream: '{0}'='{1}' Namespace Declaration requires a StartMember after StartObject '{2}'. + + + XAML Node Stream: GetObject requires a StartMember after StartObject '{0}'. + + + XAML Node Stream: GetObject must follow a StartObject and StartMember. + + + XAML Node Stream: Value of '{0}' requires a StartMember after StartObject '{1}'. + + + XAML Node Stream: Value of '{0}' must follow a StartObject and StartMember. + + + XAML Node Stream: Missing EndMember for '{0}.{1}' before EndObject. + + + XAML Node Stream: Missing EndMember for '{0}.{1}' before StartMember '{2}'. + + + XAML Node Stream: Missing StartObject before StartMember '{0}'. + + + XAML Node Stream: Missing CurrentObject before EndObject. + + + XAML Node Stream: Missing StartMember on Type '{0}' before EndMember. + + + XAML Node Stream: EndMember must follow StartObject and StartMember. + + + XAML Node Stream: Value nodes must be followed by EndMember. + + + Dictionary of type '{0}' cannot add key '{1}'. A TypeConverter will convert the key to type '{2}'. To avoid seeing this error, override System.Collections.IDictionary.Add and perform the conversion there. + + + BaseUri can only be set once at the root node (XamlXmlReader may provide a default at the root node). + + + '{0}'.'{1}' Depends on '{0}'.{1}', which was not set. + + + Close called while inside a deferred load section. + + + Unexpected close of XAML Node Stream. + + + Deferred load section was not collected in '{0}'. + + + Deferred member was not collected in '{0}'. + + + Missing case '{0}' in DeferringWriter'{1}' method. + + + Namespace '{0}' was not found in scope. + + + Cannot attach NameScope to null root instance. + + + Service provider is missing the INameResolver service. + + + Argument should be a Type Converter, Markup Extension or Null. + + + Directly Assignable Fixups must only have one name. + + + Unexpected token after end of markup extension. + + + White space is not allowed after end of markup extension. + + + Unexpected token '{0}' in rule: '{1}', in '{2}'. + + + A Constructor for '{0}' with '{1}' arguments was not found. + + + Unexpected equals sign '=' following '{0}'. Check for a missing comma separator. + + + Unexpected equals sign '=' following '{0}'='{1}'. Check for a missing comma separator. + + + Type name '{0}' cannot have a dot '.'. + + + Unexpected '{0}' in parse rule '{1}'. + + + Element ::= . EmptyElement | ( StartElement ElementBody ). + + + EmptyElement ::= . EMPTYELEMENT DIRECTIVE* ATTRIBUTE*. + + + EmptyPropertyElement ::= EMPTYPROPERTYELEMENT. + + + StartElement ::= . ELEMENT DIRECTIVE*. + + + ElementBody ::= ATTRIBUTE* ( PropertyElement | Content )* . ENDTAG. + + + NonemptyPropertyElement ::= . PROPERTYELEMENT Content? ENDTAG. + + + PropertyElement ::= EmptyPropertyElement | NonemptyPropertyElement + + + Missing '{0}' in URI '{1}'. + + + Part between semicolon ';' and equals sign '=' is not '{0}' URI '{1}'. + + + ['{0}'('{1}')] on '{2}' is not a known property. + + + ['{0}'('{1}')] on '{2}' is not a property declared on this type. + + + Error with type '{0}'. MarkupExtensions cannot use the 'UsableDuringInitialization' attribute. + + + Error with type '{0}'. It has more than one '{1}'. + + + Missing case in ClrType 'Member' lookup. + + + Unhandled BoolTypeBit. + + + Cannot determine the item type of collection type '{0}' because it has more than one Add method or ICollection<T> implementation. To make this collection type usable in XAML, add a public Add(object) method, implement System.Collections.IList or a single System.Collections.Generic.ICollection<T>. + + + Cannot determine the item type of dictionary type '{0}' because it has more than one Add method or IDictionary<K,V> implementation. To make this dictionary type usable in XAML, add a public Add(object,object) method, implement System.Collections.IDictionary or a single System.Collections.Generic.IDictionary<K,V>. + + + Cannot determine the positional parameters for type '{0}' because it has more than one constructor overload with '{1}' parameters. To make this markup extension usable in XAML, remove the duplicate constructor overload(s) or set XamlSchemaContextSettings.SupportMarkupExtensionsWithDuplicateArity to true. + + + '{0}'.'{1}' is a property without a getter and is not a valid XAML property. + + + Need to implement public/internal sorting. + + + Attachable member '{0}' was not found. + + + '{0}' is not implemented. + + + Prefix '{0}' does not map to a namespace. + + + '{0}' Line number '{1}' and line position '{2}'. + + + '{0}' Line number '{1}'. + + + Quote characters ' or " are only allowed at the start of values. + + + Unclosed quoted value. + + + Cannot parse the malformed property name '{0}'. + + + An unhandled scanner attribute was encountered. + + + Unknown type '{0}'. + + + Unknown member '{0}' on '{1}'. + + + Unknown member '{0}'. + + + Unknown member '{0}' on unknown type '{1}'. + + + Member '{0}' on type '{1}' is internal. + + + '{0}' is not allowed in attribute usage. + + + '{0}' is not allowed in element usage. + + + '{0}' is not a valid XAML member name. + + + The property element '{0}' is not contained by an object element. + + + SchemaContext on writer must be initialized before accessing the reader. + + + Thread is already started. + + + SchemaContext cannot be null. + + + Must close XamlWriter before reading from XamlNodeList. + + + Cannot write on a closed XamlWriter. + + + An attempt was made to write to a XamlWriter that has had its Closed method called. + + + Directive getter is not implemented. + + + Bad method '{0}' on '{1}'. + + + Cannot resolve type '{0}' for method '{1}'. + + + Cannot create an instance of '{0}' because XamlType is not valid. + + + Cannot create an instance of '{0}' because XamlType is not valid. + + + Attachable events are not implemented. + + + List collection is not an IList. + + + Array Add method is not implemented. + + + No Add methods found on type '{0}' for a value of type '{1}'. + + + Creating from text without a TypeConverter is not allowed. + + + Cannot set read-only property '{0}'. + + + Cannot get write-only property '{0}'. + + + The value for XmlData property '{0}' is null or not IXmlSerializable. + + + The value for XmlData property '{0}' is not an XmlReader. + + + Name resolution failure. '{0}' was not found. + + + Reference must have a Name to resolve. + + + The invocation of a method '{0}' that matches the specified binding constraints threw an exception. + + + Get property '{0}' threw an exception. + + + Set property '{0}' threw an exception. + + + Add value to collection of type '{0}' threw an exception. + + + Add value to dictionary of type '{0}' threw an exception. + + + Set connectionId threw an exception. + + + Initialization of '{0}' threw an exception. + + + Setting xml:base on '{0}' threw an exception. + + + Provide value on '{0}' threw an exception. + + + Setting xml instance on '{0}' threw an exception. + + + Getting instance of '{0}' threw an exception. + + + Deferred load threw an exception. + + + Save of deferred-load content threw an exception. + + + The factory method '{0}' that matches the specified binding constraints returned null. + + + The invocation of the constructor on type '{0}' that matches the specified binding constraints threw an exception. + + + No default constructor found for type '{0}'. You can use the Arguments or FactoryMethod directives to construct this type. + + + No matching constructor found on type '{0}'. You can use the Arguments or FactoryMethod directives to construct this type. + + + Cannot get a XamlDeferringLoader from XamlValueConverter '{0}' because its ConverterInstance property is null. + + + Failed to convert '{0}' to type '{1}'. + + + Failed to check convertibility from type '{0}' using '{1}'. This generally indicates an incorrectly implemented TypeConverter. + + + Failed to check convertibility to type '{0}' using '{1}'. This generally indicates an incorrectly implemented TypeConverter. + + + ShouldSerialize check failed for member '{0}'. + + + XamlTypeInvoker.GetItems returned null for type '{0}'. This generally indicates an incorrectly implemented collection type. + + + Retrieving items in collection or dictionary of type '{0}' threw an exception. + + + Enumerating attached properties on object '{0}' threw an exception. + + + Cannot reassign a previously set SchemaContext. + + + Cannot set SchemaContext to null. + + + Missing case in Default processing of XamlNodes. + + + TypeExtension must have TypeName property set before ProvideValue can be called. + + + '{0}' string is not valid for type. + + + Markup extension '{0}' requires '{1}' be implemented in the IServiceProvider for ProvideValue. + + + Unable to call '{0}' in current state. + + + Unable to call WriteObject with isObjectFromMember set to true in current state. + + + The prefix '{0}' is already defined in current scope. + + + Namespace '{0}' already has a prefix defined in current scope. + + + The member '{0}' has already been written. + + + The argument isObjectFromMember can only be set to true when the type is a collection. + + + Cannot write a value that is not a string. + + + Cannot write positional parameters in the current state. The writer cannot write the positional parameters in attribute form because the writer has started to write elements, nor can the writer expand the positional parameters due to the lack of a default constructor on the markup extension that contains the positional parameters. Try moving the positional parameter member earlier in the node stream, to a place where XamlXmlWriter can still write attributes. + + + Cannot write the given positional parameters because a matching constructor was not found. + + + Cannot write positional parameters in the current state. The writer cannot write the positional parameters in attribute form because the writer has started to write elements, nor can the writer expand the positional parameters since not all properties are writable. Try moving the positional parameter member earlier in the node stream, to a place where XamlXmlWriter can still write attributes. + + + The name of the type '{0}' contains characters that are invalid in XAML. + + + The name of the member '{0}' contains characters that are invalid in XAML. + + + The prefix 'xml' is reserved. + + + Cannot write positional parameters in the current state. The writer cannot write the positional parameters in attribute form because the writer has started to write elements, nor can the writer expand the positional parameters since UnderlyingType on type '{0}' is null. Try moving the positional parameter member earlier in the node stream, to place where XamlXmlWriter can still write attributes. + + + The prefix '{0}' could not be found. + + + XamlXmlWriter cannot write value '{0}' which contains significant white space in collection '{1}'. + + + The value '{1}' contains significant white space(s) but "xml:space = preserve" cannot be written down on the member '{0}'. + + + The string '{0}' is not a valid XAML type name. Type names contain an optional prefix, a name, and optional type arguments; such as 'String', 'x:Int32', 'g:Dictionary(x:String,x:Int32)'. + + + The string '{0}' is not a valid XAML type name list. Type name lists are comma-delimited lists of types; such as 'x:String, x:Int32'. + + + Character '{0}' was unexpected in string '{1}'. Invalid XAML type name. + + + Cannot convert this XamlTypeName instance to a string because the Namespace property is null. Set the Namespace property before calling XamlTypeName.ToString. + + + Cannot convert this XamlTypeName instance to a string because the Name property is null or empty. Set the Name property before calling XamlTypeName.ToString. + + + Cannot convert this XamlTypeName instance to a string because the provided INamespacePrefixLookup could not generate a prefix for the namespace '{0}'. + + + Collection '{0}' cannot contain null values. + + + NamespaceDeclaration.Prefix cannot be null. Provide a value for this property. + + + NamespaceDeclaration.Namespace cannot be null. Provide a value for this property. + + + Attached property getter methods must have one parameter and a non-void return type. + + + Attached property setter and attached event adder methods must have two parameters. + + + Either getter or setter must be non-null. + + + Unable to locate MemberMarkupInfo.DictionaryEntriesFromGeneric method. + + + An element with the name '{0}' has already been registered in this scope. + + + The object graph contains multiple references to an instance of type '{0}' and the serializer cannot find a commonly visible location to write the instance. You should examine your use of name scopes. + + + The name property '{0}' on type '{1}' must be of type System.String. + + + Unable to serialize type '{0}'. Verify that the type is public and either has a default constructor or an instance descriptor. + + + Unable to find a suitable constructor for the specified constructor arguments on type '{0}'. + + + InstanceDescriptor provided an argument of type '{0}' where a parameter of type '{1}' was expected. + + + InstanceDescriptor did not provide the correct number of arguments. + + + InstanceDescriptor did not provide a valid constructor or method. + + + Unable to read objects of the type ‘{0}’ because there are no accessible constructors. To allow this type to be used in XAML, add a default constructor, use ConstructorArgumentAttribute, or provide an InstanceDescriptor. + + + Unable to read objects of the type '{0}'. Nested types are not supported. + + + Unable to find an attachable property named '{0}' on type '{1}'. + + + Unexpected XAML node type '{0}' from XamlReader in XamlFactory. + + + In markup extensions, all constructor argument values should be atoms. For the object of type '{0}', one or more argument values are not atomic. + + + Multidimensional arrays not supported. + + + '{0}' blocked the use of type '{1}' in XAML. If you want to serialize this type, change '{0}'.GetXamlType to return a non-null value for this type, or pass a different value in the schemaContext parameter of the XamlObjectReader constructor. + + + Type '{0}' not visible. If the type is local, please set the LocalAssembly field in XamlReaderSettings. + + + Expected value of type ObjectMarkupInfo. + + + An attachable property named '{2}' is attached to a property named '{1}'. The property named '{1}' is either a string or can be type-converted to string; attaching on such properties are not supported. For debugging, the property '{1}' contains an object '{0}'. + + + An attachable property named '{1}' is attached on a dictionary key '{0}' that is either a string or can be type-converted to string, which is not supported. + + + Service provider is missing the IXamlNameProvider service. + + + Cannot set SchemaContext on XamlMarkupExtensionWriter. + + + The member '{0}' has already been written. + + + Cannot write a value that is not a string. + + + Errors detected in input. + + + Failed to add attached properties to item in ConditionalWeakTable. + + + Invalid metadata for attribute '{0}' on '{1}'. Expected '{2}' argument(s) of type '{3}'. + + + Method '{0}' is not supported by default. It can be implemented in derived classes. + + + Type name '{0}' is not assembly-qualified. You can obtain this value from System.Type.AssemblyQualifiedName. + + + Assembly name '{0}' is not fully qualified. The Name, Version, Culture, and PublicKeyToken must all be provided. + + + Expected permission of type XamlLoadPermission. + + + Invalid security XML. Unexpected tag '{0}', expected '{1}'. + + + Invalid security XML. Unexpected value '{0}' in attribute '{1}', expected '{2}'. + + + Invalid security XML. Missing expected attribute '{0}'. + + + The string is null or empty. + + + This operation is not supported on unknown types. + + + This operation is only supported on collection types. + + + This operation is only supported on dictionary types. + + + This operation is only supported on collection and dictionary types. + + + This operation is not supported on unknown members. + + + This operation is not supported on directive members. + + + One of the following arguments must be non-null: '{0}'. + + + Converter type '{0}' doesn't derive from expected base type '{1}'. + + + Value cannot be null. Object reference: '{0}'. + + + Must set Type before calling ProvideValue on ArrayExtension. + + + Items in the array must be type '{0}'. One or more items cannot be cast to this type. + + + '{0}' StaticExtension value cannot be resolved to an enumeration, static field, or static property. + + + StaticExtension must have Member property set before ProvideValue can be called. + + + '{0}' must be of type '{1}'. + + + (null) + + + '{0}' ValueSerializer cannot convert '{1}' to '{2}'. + + + '{0}' ValueSerializer cannot convert from '{1}'. + + + This serviceType is already registered to another service. + + + '{0}' type name does not have the expected format 'className, assembly'. + + + Too many attributes are specified for '{0}'. + + + '{0}' requires more attributes. + + + Cannot load assembly '{0}' because a different version of that same assembly is loaded '{1}'. + + + Cannot promote from '{0}' to '{1}' because the target map is too small. + + + Cannot promote from Array. + + + A value in the '{0}' array is null. + + + Event argument is invalid. + + + Encountered a closing BracketCharacter '{0}' without a corresponding opening BracketCharacter. + + + BracketCharacter '{0}' does not have a corresponding opening/closing BracketCharacter. + + \ No newline at end of file diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/Resources/win32res.rc b/src/Microsoft.DotNet.Wpf/src/System.Xaml/Resources/win32res.rc new file mode 100644 index 00000000000..8e1aa51e9f2 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/Resources/win32res.rc @@ -0,0 +1,11 @@ +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + + + +#include +#include + + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/SR.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/SR.cs new file mode 100644 index 00000000000..8b17d2a2423 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/SR.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Resources; + +namespace System +{ + internal static partial class SR + { + public static string Get(string name) + { + return GetResourceString(name, null); + } + + public static string Get(string name, params object[] args) + { + return Format(GetResourceString(name, null), args); + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System.Xaml.csproj b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System.Xaml.csproj new file mode 100644 index 00000000000..00ee70c1381 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System.Xaml.csproj @@ -0,0 +1,104 @@ + + + {9AC36357-34B7-40A1-95CA-FE9F46D089A7} + System.Xaml + netcoreapp3.0 + AnyCPU;x64 + + $(NoWarn);0618 + $(DefineConstants);OLDRESOURCES;SYSTEM_XAML + + + + true + + runtime.win-$(Platform) + runtime.win-x86 + + $(PackageRuntimeIdentifierPrefix).Microsoft.DotNet.Wpf.Private + Microsoft.DotNet.Wpf + + + + + Common\WPF\System\Windows\Markup\TypeConverterHelper.cs + + + + Common\WPF\System\Windows\Markup\ReflectionHelper.cs + + + Common\WPF\MS\Internal\Xaml\Parser\SpecialBracketCharacters.cs + + + Common\WPF\MS\Internal\SafeSecurityHelper.cs + + + Common\WPF\MS\Internal\SecurityCriticalDataForSet.cs + + + Common\WPF\MS\Internal\CriticalExceptions.cs + + + Common\WPF\System\Windows\Markup\RuntimeIdentifierPropertyAttribute.cs + + + Common\WPF\MS\Internal\Xaml\Context\XamlContextStack.cs + + + Common\WPF\MS\Internal\Xaml\Context\XamlFrame.cs + + + Common\WPF\System\Windows\Markup\XmlCompatibilityReader.cs + + + Common\WPF\System\Windows\Markup\XmlWrappingReader.cs + + + Common\WPF\MS\Internal\FriendAccessAllowedAttribute.cs + + + Common\WPF\MS\Utility\FrugalList.cs + + + + + + Common\System\SR.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/AcceptedMarkupExtensionExpressionTypeAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/AcceptedMarkupExtensionExpressionTypeAttribute.cs new file mode 100644 index 00000000000..bf0be20476f --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/AcceptedMarkupExtensionExpressionTypeAttribute.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace System.Windows.Markup +{ + [Obsolete("This is not used by the XAML parser. Please look at XamlSetMarkupExtensionAttribute.")] + [AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=true)] + public class AcceptedMarkupExtensionExpressionTypeAttribute: Attribute + { + public Type Type {get; set; } + + public AcceptedMarkupExtensionExpressionTypeAttribute(Type type) + { + Type = type; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/AmbientAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/AmbientAttribute.cs new file mode 100644 index 00000000000..6c3962110e5 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/AmbientAttribute.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; + +using System.Text; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Method, Inherited=true)] + public sealed class AmbientAttribute : Attribute + { + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ArrayExtension.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ArrayExtension.cs new file mode 100644 index 00000000000..a9434d82a6d --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ArrayExtension.cs @@ -0,0 +1,141 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************\ +* +* +* Class for Xaml markup extension for Arrays +* +* +\***************************************************************************/ +using System; +using System.Collections; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Xaml; + +namespace System.Windows.Markup +{ + /// + /// Class for Xaml markup extension for Arrays. + /// + [TypeForwardedFrom("PresentationFramework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + [ContentProperty("Items")] + [MarkupExtensionReturnType(typeof(Array))] + public class ArrayExtension : MarkupExtension + { + /// + /// Constructor that takes no parameters. This creates an empty array. + /// + public ArrayExtension() + { + } + + /// + /// Constructor that takes one parameter. This initializes the type of the array. + /// + public ArrayExtension( + Type arrayType) + { + if (arrayType == null) + { + throw new ArgumentNullException("arrayType"); + } + _arrayType = arrayType; + } + + /// + /// Constructor for writing + /// + /// The array to write + public ArrayExtension(Array elements) + { + if (elements == null) + { + throw new ArgumentNullException("elements"); + } + + _arrayList.AddRange(elements); + _arrayType = elements.GetType().GetElementType(); + } + + /// + /// Called to Add an object as a new array item. This will append the object to the end + /// of the array. + /// + /// + /// Object to add to the end of the array. + /// + public void AddChild(Object value) + { + _arrayList.Add(value); + } + + /// + /// Called to Add a text as a new array item. This will append the object to the end + /// of the array. + /// + /// + /// Text to Add to the end of the array + /// + public void AddText(string text) + { + AddChild(text); + } + + /// + /// Get and set the type of array to be created when calling ProvideValue + /// + [ConstructorArgument("type")] + public Type Type + { + get { return _arrayType; } + set { _arrayType = value; } + } + + /// + /// An IList accessor to the contents of the array + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] + public IList Items + { + get { return _arrayList; } + } + + /// + /// Return an array that is sized to the number of objects added to the ArrayExtension. + /// + /// Object that can provide services for the markup extension. + /// + /// The Array containing all the objects added to this extension. + /// + public override object ProvideValue(IServiceProvider serviceProvider) + { + if (_arrayType == null) + { + throw new InvalidOperationException(SR.Get(SRID.MarkupExtensionArrayType)); + } + + object retArray = null; + + try + { + retArray = _arrayList.ToArray(_arrayType); + } + catch (System.InvalidCastException) + { + // If an element was added to the ArrayExtension that does not agree with the + // ArrayType, then an InvalidCastException will occur. Generate a more + // meaningful error for this case. + throw new InvalidOperationException(SR.Get(SRID.MarkupExtensionArrayBadType, _arrayType.Name)); + } + + return retArray; + } + + private ArrayList _arrayList = new ArrayList(); + private Type _arrayType; + + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/BuildTopDownAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/BuildTopDownAttribute.cs new file mode 100644 index 00000000000..0c823b05d33 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/BuildTopDownAttribute.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; + +using System.Text; + +namespace System.Windows.Markup +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public sealed class UsableDuringInitializationAttribute : Attribute + { + bool _usable; + + public UsableDuringInitializationAttribute(bool usable) + { + _usable = usable; + } + + public bool Usable { get { return _usable; } } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ConstructorArgumentAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ConstructorArgumentAttribute.cs new file mode 100644 index 00000000000..0efa778392a --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ConstructorArgumentAttribute.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Contents: An attribute to declare that this property can be +// initialized using the classes constructor of the name +// provided. +// +// Created: 05/06/2005 Microsoft +// + +using System; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + + /// + /// Attribute to declare that this associated property can be initialized by a + /// constructor parameter and should be ignored for serialization if the constructor + /// with an argument of the supplied name is used to construct the instance. + /// + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + public sealed class ConstructorArgumentAttribute : Attribute + { + /// + /// Constructor for an ConstructorArgumentAttribute + /// + /// Name of the constructor argument that will initialize this property + public ConstructorArgumentAttribute(string argumentName) + { + _argumentName = argumentName; + } + + /// + /// Name of the constructor argument that will initialize this property + /// + public string ArgumentName + { + get { return _argumentName; } + } + + private string _argumentName; + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ContentPropertyAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ContentPropertyAttribute.cs new file mode 100644 index 00000000000..08d8685b04f --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ContentPropertyAttribute.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Description: Specifies which property of a class should be written as the +// direct content of the class when written to XAML. +// + +using System; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + + /// + /// An attribute that specifies which property the direct content of a XAML + /// element should be associated with. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class ContentPropertyAttribute : Attribute + { + + /// + /// Creates a new content property attriubte that indicates that associated + /// class does not have a content property attribute. This allows a descendent + /// remove an ancestors declaration of a content property attribute. + /// + public ContentPropertyAttribute() + { + } + + /// + /// Creates a new content property attribute that associates the direct content + /// of XAML content with property of the given name + /// + /// The property to associate to direct XAML content + public ContentPropertyAttribute(string name) + { + _name = name; + } + + /// + /// The name of the property that is associated with direct XAML content + /// + public string Name { + get { return _name; } + } + + private string _name; + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ContentWrapperAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ContentWrapperAttribute.cs new file mode 100644 index 00000000000..1c6dca4abb5 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ContentWrapperAttribute.cs @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Description: Can be specified on a collection type to indicate which +// types are used to wrap content foreign content such as +// strings in a strongly type Collection. +// +// Created: 06/07/2005 Microsoft +// + +namespace System.Windows.Markup +{ + using System; + using System.Runtime.CompilerServices; + + /// + /// Can be specified on a collection type to indicate which + /// types are used to wrap content foreign content such as + /// strings in a strongly type Collection. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + sealed public class ContentWrapperAttribute : Attribute + { + /// + /// Declares the given type as being a content wrapper for the collection + /// type this attribute is declared on. + /// + /// + public ContentWrapperAttribute(Type contentWrapper) + { + _contentWrapper = contentWrapper; + } + + /// + /// The type that is declared as a content wrapper for the collection type + /// this attribute is declared on. + /// + public Type ContentWrapper + { + get { return _contentWrapper; } + } + + /// + /// Override to ensure AttributeCollection perserves all instances + /// + public override object TypeId + { + get { return this; } + } + + + /// + /// Overrides Object.Equals to implement correct equality semantics for this + /// attribute. + /// + public override bool Equals(object obj) + { + ContentWrapperAttribute other = obj as ContentWrapperAttribute; + if (other == null) return false; + return _contentWrapper == other._contentWrapper; + } + + /// + /// Overrides Object.GetHashCode to implement correct hashing semantics. + /// + public override int GetHashCode() + { + return _contentWrapper.GetHashCode(); + } + + + private Type _contentWrapper; + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/DateTimeValueSerializer.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/DateTimeValueSerializer.cs new file mode 100644 index 00000000000..edec1591580 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/DateTimeValueSerializer.cs @@ -0,0 +1,173 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************\ +* +* +\***************************************************************************/ + +using System.Globalization; +using System.Text; +using System.Runtime.CompilerServices; +using System.Xaml; + +namespace System.Windows.Markup +{ + + //+-------------------------------------------------------------------------------------- + // + // DateTimeValueSerializer + // + // This class converts DateTime values to/from string. We don't use the DateTimeConverter + // because it doesn't support custom cultures, and in Xaml we require the converter to + // support en-us culture. + // + //+-------------------------------------------------------------------------------------- + + /// + /// ValueSerializer for DateTime. + /// + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public class DateTimeValueSerializer : ValueSerializer + { + /// + /// Initializes a new instance of the class. + /// + public DateTimeValueSerializer() + { + } + + /// + /// Indicate that we do convert DateTime's from string. + /// + + public override bool CanConvertFromString(string value, IValueSerializerContext context) + { + return true; + } + + /// + /// Indicate that we do convert a DateTime to string. + /// + + public override bool CanConvertToString(object value, IValueSerializerContext context) + { + // Validate the input type + if ( !(value is DateTime)) + { + return false; + } + + return true; + } + + /// + /// Converts the given value object to a . + /// + + public override object ConvertFromString(string value, IValueSerializerContext context) + { + // Validate and clean up input. + + if( value == null ) + { + throw GetConvertFromException(value); + } + + if( value.Length == 0 ) + { + return DateTime.MinValue; + } + + // Get a DateTimeFormatInfo + + DateTimeFormatInfo dateTimeFormatInfo; + + dateTimeFormatInfo = (DateTimeFormatInfo)TypeConverterHelper.InvariantEnglishUS.GetFormat(typeof(DateTimeFormatInfo)); + + // Set the formatting style for round-tripping and to trim the string. + + DateTimeStyles dateTimeStyles = DateTimeStyles.RoundtripKind + | DateTimeStyles.NoCurrentDateDefault + | DateTimeStyles.AllowLeadingWhite + | DateTimeStyles.AllowTrailingWhite; + + // Create the DateTime, using the DateTimeInfo if possible, and the culture otherwise. + + if (dateTimeFormatInfo != null) + { + return DateTime.Parse(value, dateTimeFormatInfo, dateTimeStyles); + } + else + { + // The culture didn't have a DateTimeFormatInfo. + return DateTime.Parse(value, TypeConverterHelper.InvariantEnglishUS, dateTimeStyles); + } + } + + + + /// + /// Converts the given value object to a using the arguments. + /// + + public override string ConvertToString(object value, IValueSerializerContext context) + { + if( value == null || !(value is DateTime)) + { + throw GetConvertToException( value, typeof(string) ); + } + + DateTime dateTime = (DateTime)value; + + // Build up the format string to be used in DateTime.ToString() + StringBuilder formatString = new StringBuilder("yyyy-MM-dd"); + + if (dateTime.TimeOfDay.TotalSeconds == 0) + { + // The time portion of this DateTime is exactly at midnight. + // We don't include the time component if the Kind is unspecified. + // Otherwise, we're going to be including the time zone info, so'll + // we'll have to include the time. + + if( dateTime.Kind != DateTimeKind.Unspecified ) + { + formatString.Append("'T'HH':'mm"); + } + } + + else + { + long digitsAfterSecond = dateTime.Ticks % 10000000; + int second = dateTime.Second; + // We're going to write out at least the hours/minutes + formatString.Append("'T'HH':'mm"); + if (second != 0 || digitsAfterSecond != 0) + { + // need to write out seconds + formatString.Append("':'ss"); + if (digitsAfterSecond != 0) + { + // need to write out digits after seconds + formatString.Append("'.'FFFFFFF"); + } + } + } + + // Add the format specifier that indicates we want the DateTimeKind to be + // included in the output formulation -- UTC gets written out with a "Z", + // and Local gets written out with e.g. "-08:00" for Pacific Standard Time. + + formatString.Append("K"); + + // We've finally got our format string built, we can create the string. + + return dateTime.ToString(formatString.ToString(), TypeConverterHelper.InvariantEnglishUS ); + + } + + } + +} + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/DependsOnAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/DependsOnAttribute.cs new file mode 100644 index 00000000000..aa9586376f1 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/DependsOnAttribute.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Contents: An attribute that allows declaring that one property +// depends on the value of another property. The serialization +// system will ensure that the listed property is serialized +// prior to the property that this attribute is set on. +// Care must be taken to avoid circular dependencies. They +// are only detected when writing all the properties in the +// cycle. +// +// Created: 04/28/2005 Microsoft +// + +using System; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// DependsOnAttribute allows declaring that one property + /// depends on the value of another property. The serialization + /// system will ensure that the listed property is serialized + /// prior to the property that this attribute is set on. + /// Care must be taken to avoid circular dependencies. They + /// are only detected when writing all the properties in the + /// cycle. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method, AllowMultiple=true)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class DependsOnAttribute : Attribute + { + /// + /// Constructor for DependsOnAttribute + /// + /// The name of the property that the property depends on + public DependsOnAttribute(string name) + { + _name = name; + } + + /// + /// Override of Attribute.TypeId + /// + public override object TypeId + { + // this allows multiple DependsOn attributes to show up in the + // PropertyDescriptor.Attributes collection. + get { return this; } + } + + /// + /// The name of the property that is declared to depend on + /// + public string Name + { + get { return _name; } + } + + private string _name; + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/DictionaryKeyPropertyAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/DictionaryKeyPropertyAttribute.cs new file mode 100644 index 00000000000..5b1c58bdcad --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/DictionaryKeyPropertyAttribute.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; + +using System.Text; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class DictionaryKeyPropertyAttribute : Attribute + { + string _name; + + public DictionaryKeyPropertyAttribute(string name) + { + _name = name; + } + + public string Name { get { return _name; } } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IComponentConnector.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IComponentConnector.cs new file mode 100644 index 00000000000..a93bbd851e6 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IComponentConnector.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// +// Description: +// Provides methods used internally by the BamlReader to initialize a component +// and connect Names and events on elements in its content. The markup compiler +// generates an implementation of this interface for the sub-class of the root +// markup element that it also generates. +// +// + +using System.Runtime.CompilerServices; +namespace System.Windows.Markup +{ + /// + /// Provides methods used internally by the BamlReader + /// on compiled content. + /// + /// + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public interface IComponentConnector + { + /// + /// Called by the BamlReader to attach events and Names on compiled content. + /// + void Connect(int connectionId, object target); + + /// + /// Called by a component to load its compiled content. + /// + void InitializeComponent(); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/INameScope.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/INameScope.cs new file mode 100644 index 00000000000..0fb897f273e --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/INameScope.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Description: Defines the basic Name Scoping interface for root classes + +using System; +using System.ComponentModel; +using System.Windows; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// INameScope- Defines the basic Name Scoping interface for root classes + /// + /// + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public interface INameScope + { + /// + /// Registers the name - element combination + /// + /// Name of the element + /// Element where name is defined + void RegisterName(string name, object scopedElement); + + /// + /// Unregisters the name - element combination + /// + /// Name of the element + void UnregisterName(string name); + + /// + /// Find the element given name + /// + object FindName(string name); + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/INameScopeDictionary.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/INameScopeDictionary.cs new file mode 100644 index 00000000000..d2aa5d76c7d --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/INameScopeDictionary.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Windows; +using System.Collections.Generic; + +namespace System.Windows.Markup +{ + public interface INameScopeDictionary : INameScope, IDictionary + { + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IProvideValueTarget.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IProvideValueTarget.cs new file mode 100644 index 00000000000..8ce9daa13e0 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IProvideValueTarget.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// +// Description: +// Provides a way to get the object and property onto which +// a MarkupExtension is being set. This is used by a few +// MarkupExtension.ProvideValue implementations. +// +// + +using System; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// This interface is used for MarkupExtension's to indicate + /// in the ProvideValue method the object and property to which + /// this value will be set. The TargetObject and TargetProperty + /// values may be null. + /// + [TypeForwardedFrom("PresentationFramework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public interface IProvideValueTarget + { + /// + /// + object TargetObject { get; } + + /// + /// + object TargetProperty { get; } + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IQueryAmbient.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IQueryAmbient.cs new file mode 100644 index 00000000000..83226ed66ed --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IQueryAmbient.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Windows.Markup +{ + public interface IQueryAmbient + { + bool IsAmbientPropertyAvailable(string propertyName); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IUriContext.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IUriContext.cs new file mode 100644 index 00000000000..0d168904e9f --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IUriContext.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.ComponentModel; +using System; +using MS.Internal; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// The IUriContext interface allows elements (like Frame, PageViewer) and type converters + /// (like BitmapImage TypeConverters) a way to ensure that base uri is set on them by the + /// parser, codegen for xaml, baml and caml cases. The elements can then use this base uri + /// to navigate. + /// + [TypeForwardedFrom("PresentationCore, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public interface IUriContext + { + /// + /// Provides the base uri of the current context. + /// + Uri BaseUri + { + get; + set; + } + } + + +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IValueSerializerContext.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IValueSerializerContext.cs new file mode 100644 index 00000000000..eb1204de2e7 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IValueSerializerContext.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Contents: Context interface for value serializers +// +// Created: 04/28/2005 Microsoft +// + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// Context provided to ValueSerializer that can be used to special case serialization for different users of the + /// ValueSerializaer or for modes of serialization. + /// + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public interface IValueSerializerContext : ITypeDescriptorContext + { + + /// + /// Get the value serializer associated with the given type. + /// + /// The type of the value that is to be convert + /// A value serializer for capable of serializing the given type + ValueSerializer GetValueSerializerFor(Type type); + + /// + /// Get a value serializer for the given property descriptor. A property can override the value serializer that + /// is to be used to serialize the property by specifing either a ValueSerializerAttribute or a + /// TypeConverterAttribute. This method takes these attributes into account when determining the value + /// serializer. + /// + /// The property descriptor for whose property value is being converted + /// A value serializer capable of serializing the given property + ValueSerializer GetValueSerializerFor(PropertyDescriptor descriptor); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IXamlTypeResolver.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IXamlTypeResolver.cs new file mode 100644 index 00000000000..f3817e64e7e --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/IXamlTypeResolver.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// +// Description: +// Provides a publicly exposable way to resolve a type from its +// QName (e.g. the ns:Class in Xaml). +// +// + +using System; +using System.Windows; +using System.Reflection; +using System.Globalization; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// Provides services to help resolve nsPrefix:LocalName into the appropriate Type. + /// + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public interface IXamlTypeResolver + { + /// + /// Resolves nsPrefix:LocalName into the appropriate Type. + /// + /// TypeName that appears in Xaml - nsPrefix:LocalName or LocalName. + /// + /// The type that the qualifiedTypeName represents. + /// + + Type Resolve(string qualifiedTypeName); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MarkupExtension.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MarkupExtension.cs new file mode 100644 index 00000000000..aae5e2c891f --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MarkupExtension.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Windows; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// Base class for all Xaml markup extensions. Only subclasses can + /// be instantiated. + /// + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public abstract class MarkupExtension + { + /// + /// Return an object that should be set on the targetObject's targetProperty + /// for this markup extension. + /// + /// Object that can provide services for the markup extension. + /// + /// The object to set on this property. + /// + public abstract object ProvideValue(IServiceProvider serviceProvider); + + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MarkupExtensionBracketCharactersAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MarkupExtensionBracketCharactersAttribute.cs new file mode 100644 index 00000000000..600ba15a9dc --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MarkupExtensionBracketCharactersAttribute.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.ObjectModel; +using System.Text; + +namespace System.Windows.Markup +{ + /// + /// Attribute to declare that this associated property will have special parsing rules + /// for any text that is enclosed between these special characters. + /// + [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)] + public sealed class MarkupExtensionBracketCharactersAttribute : Attribute + { + /// + /// Constructor for an MarkupExtensionBracketCharactersAttribute + /// + /// Opening character for the Bracket characters. For example, '(' , '[' + /// /// Closing character for the Bracket characters. For example, ')' , ']' + public MarkupExtensionBracketCharactersAttribute(char openingBracket, char closingBracket) + { + OpeningBracket = openingBracket; + ClosingBracket = closingBracket; + } + + public char OpeningBracket { get; } + public char ClosingBracket { get; } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MarkupExtensionReturnTypeAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MarkupExtensionReturnTypeAttribute.cs new file mode 100644 index 00000000000..e24b98d36f6 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MarkupExtensionReturnTypeAttribute.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Description: Describes what type a markup extension can return. +// +// Created: 11/17/2005 +// + +using System; + +namespace System.Windows.Markup +{ + + /// + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)] + public sealed class MarkupExtensionReturnTypeAttribute : Attribute + { + + /// + /// + public MarkupExtensionReturnTypeAttribute(Type returnType) + { + _returnType = returnType; + } + + [Obsolete("The expressionType argument is not used by the XAML parser. To specify the expected return type, " + + "use MarkupExtensionReturnTypeAttribute(Type). To specify custom handling for expression types, use " + + "XamlSetMarkupExtensionAttribute.")] + public MarkupExtensionReturnTypeAttribute(Type returnType, Type expressionType) + { + _returnType = returnType; + _expressionType = expressionType; + } + + /// + /// + public MarkupExtensionReturnTypeAttribute() + { + } + + /// + /// + public Type ReturnType + { + get { return _returnType; } + } + + [Obsolete("This is not used by the XAML parser. Please look at XamlSetMarkupExtensionAttribute.")] + public Type ExpressionType + { + get { return _expressionType; } + } + + private Type _returnType; + private Type _expressionType; + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MemberDefinition.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MemberDefinition.cs new file mode 100644 index 00000000000..ae5a20fbe41 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/MemberDefinition.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Windows.Markup +{ + public abstract class MemberDefinition + { + public abstract string Name { get; set; } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/NameScopePropertyAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/NameScopePropertyAttribute.cs new file mode 100644 index 00000000000..a002d2ae3b0 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/NameScopePropertyAttribute.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.CompilerServices; + + +namespace System.Windows.Markup +{ + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class NameScopePropertyAttribute : Attribute + { + private string _name; + private Type _type; + + // Methods + public NameScopePropertyAttribute (string name) + { + _name = name; + } + + public NameScopePropertyAttribute (string name, Type type) + { + _name = name; + _type = type; + } + + + // Properties + public string Name { get{ return _name;} } + public Type Type { get{ return _type;} } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/NullExtension.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/NullExtension.cs new file mode 100644 index 00000000000..3581b0eaf1f --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/NullExtension.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************\ +* +* +* Class for Xaml markup extension {Null} +* +* +\***************************************************************************/ +using System; +using System.Windows; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// Class for Xaml markup extension for Null. + /// + [TypeForwardedFrom("PresentationFramework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + [MarkupExtensionReturnType(typeof(object))] + public class NullExtension : MarkupExtension + { + /// + /// Default constructor + /// + public NullExtension() + { + } + + /// + /// Return an object that should be set on the targetObject's targetProperty + /// for this markup extension. In this case it is simply null. + /// + /// Object that can provide services for the markup extension. + /// + /// The object to set on this property. + /// + public override object ProvideValue(IServiceProvider serviceProvider) + { + return null; + } + + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/PropertyDefinition.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/PropertyDefinition.cs new file mode 100644 index 00000000000..fa342451e30 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/PropertyDefinition.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Xaml; +using System.Xaml.Schema; + +namespace System.Windows.Markup +{ + public class PropertyDefinition : MemberDefinition + { + private IList attributes; + + public override string Name { get; set; } + + [TypeConverter(typeof(XamlTypeTypeConverter))] + public XamlType Type { get; set; } + + [DefaultValue(null)] + public string Modifier { get; set; } + + public IList Attributes + { + get + { + if (attributes == null) + { + attributes = new List(); + } + return attributes; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/RootNamespaceAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/RootNamespaceAttribute.cs new file mode 100644 index 00000000000..cf8757467bb --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/RootNamespaceAttribute.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// +// Description: +// RootNamespaceAttribute is an assembly level attribute is used to identify +// the value of the RootNamespace property in a project file. +// +// + +using System; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + + /// + /// An attribute that identifies the value of the RootNamespace property in a project file. + /// + [AttributeUsage(AttributeTargets.Assembly)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class RootNamespaceAttribute : Attribute + { + /// + /// Creates a new RootNamespaceAttribute that describes the value of the RootNamespace + /// property in a project file. + /// + /// The root namespace value + public RootNamespaceAttribute(string nameSpace) + { + _nameSpace = nameSpace; + } + + /// + /// The root namespace value corresponding to the value of the RootNamespace property in a project file. + /// + public string Namespace + { + get { return _nameSpace; } + } + + private string _nameSpace; + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/StaticExtension.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/StaticExtension.cs new file mode 100644 index 00000000000..233488eedb0 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/StaticExtension.cs @@ -0,0 +1,209 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.ComponentModel.Design.Serialization; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Xaml; + +namespace System.Windows.Markup +{ + /// + /// Class for Xaml markup extension for static field and property references. + /// + [TypeForwardedFrom("PresentationFramework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + [TypeConverter(typeof(StaticExtensionConverter))] + [MarkupExtensionReturnType(typeof(object))] + public class StaticExtension : MarkupExtension + { + /// + /// Constructor that takes no parameters + /// + public StaticExtension() + { + } + + /// + /// Constructor that takes the member that this is a static reference to. + /// This string is of the format + /// Prefix:ClassName.FieldOrPropertyName. The Prefix is + /// optional, and refers to the XML prefix in a Xaml file. + /// + public StaticExtension( + string member) + { + if (member == null) + { + throw new ArgumentNullException("member"); + } + _member = member; + } + + /// + /// Return an object that should be set on the targetObject's targetProperty + /// for this markup extension. For a StaticExtension this is a static field + /// or property value. + /// + /// Object that can provide services for the markup extension. + /// + /// The object to set on this property. + /// + public override object ProvideValue(IServiceProvider serviceProvider) + { + if (_member == null) + { + throw new InvalidOperationException(SR.Get(SRID.MarkupExtensionStaticMember)); + } + + object value; + Type type = MemberType; + string fieldString = null; + string memberFullName = null; + if (type != null) + { + fieldString = _member; + memberFullName = type.FullName + "." + _member; + } + else + { + memberFullName = _member; + + // Validate the _member + + int dotIndex = _member.IndexOf('.'); + if (dotIndex < 0) + { + throw new ArgumentException(SR.Get(SRID.MarkupExtensionBadStatic, _member)); + } + + // Pull out the type substring (this will include any XML prefix, e.g. "av:Button") + + string typeString = _member.Substring(0, dotIndex); + if (typeString == string.Empty) + { + throw new ArgumentException(SR.Get(SRID.MarkupExtensionBadStatic, _member)); + } + + // Get the IXamlTypeResolver from the service provider + + if (serviceProvider == null) + { + throw new ArgumentNullException("serviceProvider"); + } + + IXamlTypeResolver xamlTypeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver; + if (xamlTypeResolver == null) + { + throw new ArgumentException(SR.Get(SRID.MarkupExtensionNoContext, GetType().Name, "IXamlTypeResolver")); + } + + // Use the type resolver to get a Type instance + + type = xamlTypeResolver.Resolve(typeString); + + // Get the member name substring + + fieldString = _member.Substring(dotIndex + 1, _member.Length - dotIndex - 1); + if (fieldString == string.Empty) + { + throw new ArgumentException(SR.Get(SRID.MarkupExtensionBadStatic, _member)); + } + } + + // Use the built-in parser for enum types + + if (type.IsEnum) + { + return Enum.Parse(type, fieldString); + } + + // For other types, reflect + if (GetFieldOrPropertyValue(type, fieldString, out value)) + { + return value; + } + else + { + throw new ArgumentException(SR.Get(SRID.MarkupExtensionBadStatic, memberFullName)); + } + } + + // return false if a public static field or property with the same name cannot be found. + private bool GetFieldOrPropertyValue(Type type, string name, out object value) + { + FieldInfo field = null; + Type temp = type; + + do + { + field = temp.GetField(name, BindingFlags.Public | BindingFlags.Static); + if (field != null) + { + value = field.GetValue(null); + return true; + } + + temp = temp.BaseType; + } while(temp != null); + + + PropertyInfo prop = null; + temp = type; + + do + { + prop = temp.GetProperty(name, BindingFlags.Public | BindingFlags.Static); + if (prop != null) + { + value = prop.GetValue(null,null); + return true; + } + + temp = temp.BaseType; + } while(temp != null); + + value = null; + return false; + } + + /// + /// The static field or property represented by a string. This string is + /// of the format Prefix:ClassName.FieldOrPropertyName. The Prefix is + /// optional, and refers to the XML prefix in a Xaml file. + /// + [ConstructorArgument("member")] + public string Member + { + get { return _member; } + set + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + _member = value; + } + } + + [DefaultValue(null)] + public Type MemberType + { + get { return _memberType; } + set + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + _memberType = value; + } + } + + private string _member; + private Type _memberType; + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/StaticExtensionConverter.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/StaticExtensionConverter.cs new file mode 100644 index 00000000000..6d26d5e3e3e --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/StaticExtensionConverter.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Contents: Converter to convert StaticExtensions to InstanceDescriptors + +// Created: 04/28/2005 Microsoft +// + +using System; +using System.ComponentModel; +using System.ComponentModel.Design.Serialization; +using System.Collections.Generic; +using System.Text; +using System.Security; +using System.Xaml; + +namespace System.Windows.Markup +{ + class StaticExtensionConverter : TypeConverter + { + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(InstanceDescriptor)) + { + return true; + } + return base.CanConvertTo(context, destinationType); + } + + /// + /// Critical: calls InstanceDescriptor ctor which LinkDemands + /// TreatAsSafe: can only make an InstanceDescriptor for StaticExtension, not an arbitrary class + /// + [SecurityCritical, SecurityTreatAsSafe] + public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) + { + if (destinationType == typeof(InstanceDescriptor)) + { + StaticExtension staticExtension = value as StaticExtension; + if (staticExtension == null) + throw new ArgumentException(SR.Get(SRID.MustBeOfType, "value", "StaticExtension")); + return new InstanceDescriptor(typeof(StaticExtension).GetConstructor(new Type[] { typeof(string) }), + new object[] { staticExtension.Member }); + } + return base.ConvertTo(context, culture, value, destinationType); + } + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/TrimSurroundingWhitespaceAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/TrimSurroundingWhitespaceAttribute.cs new file mode 100644 index 00000000000..f70c2c5e51e --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/TrimSurroundingWhitespaceAttribute.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Description: Specifies that the whitespace surrounding an element should be trimmed. +// +// Created: 02/06/2006 +// + +using System; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + + /// + /// An attribute that specifies that the whitespace surrounding an element should be trimmed + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class TrimSurroundingWhitespaceAttribute : Attribute + { + /// + /// Creates a new trim surrounding whitespace attribute. + /// + public TrimSurroundingWhitespaceAttribute() + { + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/TypeExtension.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/TypeExtension.cs new file mode 100644 index 00000000000..5af4031e3a7 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/TypeExtension.cs @@ -0,0 +1,157 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************\ +* +* +* Class for Xaml markup extension for a Type reference +* +* +\***************************************************************************/ +using System; +using System.Windows; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Xaml; + +namespace System.Windows.Markup +{ + /// + /// Class for Xaml markup extension for a Type reference. + /// + [TypeForwardedFrom("PresentationFramework, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + [TypeConverter(typeof(TypeExtensionConverter))] + [MarkupExtensionReturnType(typeof(Type))] + public class TypeExtension : MarkupExtension + { + /// + /// Default Constructor + /// + public TypeExtension() + { + } + + /// + /// Constructor that takes a type name + /// + public TypeExtension(string typeName) + { + if (typeName == null) + { + throw new ArgumentNullException("typeName"); + } + + _typeName = typeName; + } + + /// + /// Constructor that takes a type + /// + public TypeExtension(Type type) + { + if (type == null) + { + throw new ArgumentNullException("type"); + } + + _type = type; + // we would like to set TypeName here, but we can't because we can't resolve its namespace + } + + /// + /// Return an object that should be set on the targetObject's targetProperty + /// for this markup extension. TypeExtension resolves a string into a Type + /// and returns it. + /// + /// Object that can provide services for the markup extension. + /// + /// The object to set on this property. + /// + public override object ProvideValue(IServiceProvider serviceProvider) + { + // If a type was supplied, no context nor type name are needed + + if (_type != null) + { + return _type; + } + + // Validate the initialization + + if (_typeName == null) + { + throw new InvalidOperationException(SR.Get(SRID.MarkupExtensionTypeName)); + } + + // Get the IXamlTypeResolver from the service provider + + if (serviceProvider == null) + { + throw new ArgumentNullException("serviceProvider"); + } + + IXamlTypeResolver xamlTypeResolver = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver; + if( xamlTypeResolver == null ) + { + throw new InvalidOperationException( SR.Get(SRID.MarkupExtensionNoContext, GetType().Name, "IXamlTypeResolver" )); + } + + // Get the type + + _type = xamlTypeResolver.Resolve(_typeName); + + if (_type == null) + { + throw new InvalidOperationException(SR.Get(SRID.MarkupExtensionTypeNameBad, _typeName)); + } + + return _type; + // we could cash the result of type as _type, but it might cause some problems, and in theory we shouldn't need to + } + + /// + /// The typename represented by this markup extension. The name has the format + /// Prefix:Typename, where Prefix is the xml namespace prefix for this type. + /// + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public string TypeName + { + get { return _typeName; } + set + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + + _typeName = value; + _type = null; // so that ProvideValue does not use the existing type + } + } + + /// + /// The type represented by this markup extension. + /// + [DefaultValue(null)] + [ConstructorArgument("type")] + public Type Type + { + get { return _type; } + set + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + + _type = value; + _typeName = null; // so that ProvideValue does not use the existing typeName + } + } + + private string _typeName; + private Type _type; + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/TypeExtensionConverter.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/TypeExtensionConverter.cs new file mode 100644 index 00000000000..a8defc06aaa --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/TypeExtensionConverter.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Contents: Converter to convert TypeExtensions to InstanceDescriptors + +// Created: 04/28/2005 Microsoft +// + +using System; +using System.ComponentModel; +using System.ComponentModel.Design.Serialization; +using System.Collections.Generic; +using System.Text; +using System.Security; +using System.Xaml; + +namespace System.Windows.Markup +{ + class TypeExtensionConverter : TypeConverter + { + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(InstanceDescriptor)) + { + return true; + } + return base.CanConvertTo(context, destinationType); + } + + /// + /// Critical: calls InstanceDescriptor ctor which LinkDemands + /// TreatAsSafe: can only make an InstanceDescriptor for TypeExtension, not an arbitrary class + /// + [SecurityCritical, SecurityTreatAsSafe] + public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) + { + if (destinationType == typeof(InstanceDescriptor)) + { + TypeExtension typeExtension = value as TypeExtension; + if (typeExtension == null) + { + throw new ArgumentException(SR.Get(SRID.MustBeOfType, "value", "TypeExtension")); + } + return new InstanceDescriptor(typeof(TypeExtension).GetConstructor(new Type[] { typeof(Type) }), + new object[] { typeExtension.Type }); + } + return base.ConvertTo(context, culture, value, destinationType); + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/UidPropertyAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/UidPropertyAttribute.cs new file mode 100644 index 00000000000..717bd920faa --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/UidPropertyAttribute.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// +// Description: +// This attribute is placed on a class to identify it as the place to set +// the value of the x:Uid attribute from the XML markup file. +// +// Example: +// [UidProperty("Uid")] +// public class ExampleFrameworkElement +// +// Means that when the parser sees: +// +// +// +// The parser will set the "Uid" property with the value "efe1". +// +// +// + +using System; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// An attribute that specifies which property the xml:lang value should + /// be directed to. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple=false)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class UidPropertyAttribute : Attribute + { + /// + /// Creates a new UidPropertyAttribute with the given string + /// as the property name. + /// + public UidPropertyAttribute(string name) + { + _name = name; + } + + /// + /// The name of the property that is designated to accept the x:Uid value + /// + public string Name + { + get + { + return _name; + } + } + + // The name of the property that is designated to accept the x:Uid value + private string _name = null; + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ValueSerializer.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ValueSerializer.cs new file mode 100644 index 00000000000..a4b63e63cfa --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ValueSerializer.cs @@ -0,0 +1,285 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Contents: Service for providing and finding custom serialization for +// value and value like types. +// +// Created: 04/28/2005 Microsoft +// + +using System.ComponentModel; +using System.Collections; +using System.Collections.Generic; +using MS.Internal.Serialization; +using System.Xaml.Replacements; //DateTimeConverter2 +using System.Xaml; +using System.Runtime.CompilerServices; //SRID + +#pragma warning disable 1634, 1691 // suppressing PreSharp warnings + +namespace System.Windows.Markup +{ + /// + /// ValueSerializer allows a type to declare a serializer to control how the type is serializer to and from string + /// If a TypeConverter is declared for a type that converts to and from a string, a default value serializer will + /// be created for the type. The string values must be loss-less (i.e. converting to and from a string doesn't loose + /// data) and must be stable (i.e. returns the same string for the same value). If a type converter doesn't meet + /// these requirements, a custom ValueSerializer must be declared that meet the requirements or associate a null + /// ValueSerializer with the type to indicate the type converter should be ignored. Implementation of ValueSerializer + /// should avoid throwing exceptions. Any exceptions thrown could possibly terminate serialization. + /// + /// + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public abstract class ValueSerializer + { + /// + /// Constructor for a ValueSerializer + /// + protected ValueSerializer() { } + + /// + /// Returns true if the given value can be converted to a string. + /// + /// Value to convert + /// Context information + /// Whether or not the value can be converted to a string + public virtual bool CanConvertToString(object value, IValueSerializerContext context) + { + return false; + } + + /// + /// Returns true if the given value can be converted from a string. + /// + /// The string to convert + /// Context information + /// Whether or not the value can be converted from a string + public virtual bool CanConvertFromString(string value, IValueSerializerContext context) + { + return false; + } + + /// + /// Converts the given value to a string for use in serialization. This method should only be + /// called if CanConvertToString returns true for the given value. + /// + /// The value to convert to a string + /// Context information + /// A string representation of value + public virtual string ConvertToString(object value, IValueSerializerContext context) + { + throw GetConvertToException(value, typeof(string)); + } + + /// + /// Convert a string to an object. This method should only be called if CanConvertFromString + /// returns true for the given string. + /// + /// The string value to convert + /// Context information + /// An object corresponding to the string value + public virtual object ConvertFromString(string value, IValueSerializerContext context) + { + throw GetConvertFromException(value); + } + + static List Empty = new List(); + + /// + /// Returns an enumeration of the types referenced by the value serializer. If the value serializer asks for + /// a value serializer for System.Type, any types it asks to convert should be supplied in the returned + /// enumeration. This allows a serializer to ensure a de-serializer has enough information about the types + /// this serializer converts. + /// + /// Since a value serializer doesn't exist by default, it is important the value serializer be requested from + /// the IValueSerializerContext, not ValueSerializer.GetSerializerFor. This allows a serializer to encode + /// context information (such as xmlns definitions) to the System.Type converter (for example, which prefix + /// to generate). + /// + /// The value being serialized + /// Context information + /// An enumeration of the types converted by this serializer + public virtual IEnumerable TypeReferences(object value, IValueSerializerContext context) + { + return Empty; + } + + /// + /// Get the value serializer declared for the given type. + /// + /// The value type to serialize + /// The value serializer associated with the given type + public static ValueSerializer GetSerializerFor(Type type) + { + if (type == null) + throw new ArgumentNullException("type"); + + object value = _valueSerializers[type]; + if (value != null) + // This uses _valueSerializersLock's instance as a sentinal for null (as opposed to not attempted yet). + return value == _valueSerializersLock ? null : value as ValueSerializer; + + AttributeCollection attributes = TypeDescriptor.GetAttributes(type); + ValueSerializerAttribute attribute = attributes[typeof(ValueSerializerAttribute)] as ValueSerializerAttribute; + ValueSerializer result = null; + + if (attribute != null) + result = (ValueSerializer)Activator.CreateInstance(attribute.ValueSerializerType); + + if (result == null) + { + if (type == typeof(string)) + { + result = new StringValueSerializer(); + } + else + { + // Try to use the type converter + TypeConverter converter = TypeConverterHelper.GetTypeConverter(type); + + // DateTime is a special-case. We can't use the DateTimeConverter, because it doesn't + // support anything other than user culture and invariant culture, and we need to specify + // en-us culture. + if (converter.GetType() == typeof(DateTimeConverter2)) + { + result = new DateTimeValueSerializer(); + } + else if (converter.CanConvertTo(typeof(string)) && converter.CanConvertFrom(typeof(string)) && + !(converter is ReferenceConverter)) + { + result = new TypeConverterValueSerializer(converter); + } + } + } + lock (_valueSerializersLock) + { + // This uses _valueSerializersLock's instance as a sentinal for null (as opposed to not attempted yet). + _valueSerializers[type] = result == null ? _valueSerializersLock : result; + } + + return result; + } + + /// + /// Get the value serializer declared for the given property. ValueSerializer can be overriden by an attribute + /// on the property declaration. + /// + /// PropertyDescriptor for the property to be serialized + /// A value serializer associated with the given property + public static ValueSerializer GetSerializerFor(PropertyDescriptor descriptor) + { + ValueSerializer result; + if (descriptor == null) + { + throw new ArgumentNullException("descriptor"); + } + + #pragma warning suppress 6506 // descriptor is obviously not null + ValueSerializerAttribute serializerAttribute = descriptor.Attributes[typeof(ValueSerializerAttribute)] as ValueSerializerAttribute; + if (serializerAttribute != null) + { + result = (ValueSerializer)Activator.CreateInstance(serializerAttribute.ValueSerializerType); + } + else + { + result = GetSerializerFor(descriptor.PropertyType); + if (result == null || result is TypeConverterValueSerializer) + { + TypeConverter converter = descriptor.Converter; + if (converter!=null && converter.CanConvertTo(typeof(string)) && converter.CanConvertFrom(typeof(string)) && + !(converter is ReferenceConverter)) + result = new TypeConverterValueSerializer(converter); + } + } + return result; + } + + /// + /// Get the value serializer declared for the given type. This version should be called whenever the caller + /// has a IValueSerializerContext to ensure that the correct value serializer is returned for the given + /// context. + /// + /// The value type to serialize + /// Context information + /// The value serializer associated with the given type + public static ValueSerializer GetSerializerFor(Type type, IValueSerializerContext context) + { + if (context != null) + { + ValueSerializer result = context.GetValueSerializerFor(type); + if (result != null) + return result; + } + return GetSerializerFor(type); + } + + /// + /// Get the value serializer declared for the given property. ValueSerializer can be overriden by an attribute + /// on the property declaration. This version should be called whenever the caller has a + /// IValueSerializerContext to ensure that the correct value serializer is returned for the given context. + /// + /// PropertyDescriptor for the property to be serialized + /// Context information + /// A value serializer associated with the given property + public static ValueSerializer GetSerializerFor(PropertyDescriptor descriptor, IValueSerializerContext context) + { + if (context != null) + { + ValueSerializer result = context.GetValueSerializerFor(descriptor); + if (result != null) + return result; + } + return GetSerializerFor(descriptor); + } + + /// + /// Return a exception to throw if the value cannot be converted + /// + protected Exception GetConvertToException(object value, Type destinationType) + { + string text; + if (value == null) + { + text = SR.Get(SRID.ToStringNull); + } + else + { + text = value.GetType().FullName; + } + return new NotSupportedException(SR.Get(SRID.ConvertToException, base.GetType().Name, text, destinationType.FullName)); + } + + /// + /// Return a exception to throw if the string cannot be converted + /// + protected Exception GetConvertFromException(object value) + { + string text; + if (value == null) + { + text = SR.Get(SRID.ToStringNull); + } + else + { + text = value.GetType().FullName; + } + return new NotSupportedException(SR.Get(SRID.ConvertFromException, base.GetType().Name, text)); + } + + private static void TypeDescriptorRefreshed(RefreshEventArgs args) { + _valueSerializers = new Hashtable(); + } + + static ValueSerializer() { + TypeDescriptor.Refreshed += TypeDescriptorRefreshed; + } + + private static object _valueSerializersLock = new object(); + private static Hashtable _valueSerializers = new Hashtable(); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ValueSerializerAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ValueSerializerAttribute.cs new file mode 100644 index 00000000000..6896c0daaad --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/ValueSerializerAttribute.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Contents: An attribute that allows associating a ValueSerializer +// implementation with either a type or a property (or +// an attached property by setting it on the static accessor +// for the attachable property). +// +// Created: 04/28/2005 Microsoft +// + +using System; +using System.Runtime.CompilerServices; + +[assembly:TypeForwardedTo(typeof(System.Windows.Markup.ValueSerializerAttribute))] diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/WhitespaceSignificantCollectionAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/WhitespaceSignificantCollectionAttribute.cs new file mode 100644 index 00000000000..e08576b42bb --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/WhitespaceSignificantCollectionAttribute.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Description: Specifies if a collection considers whitespacing to be significant for each of its "children." + +using System; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + + /// + /// An attribute that specifies that a collection considers whitespacing to be significant. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class WhitespaceSignificantCollectionAttribute : Attribute + { + + /// + /// Creates a new content property attriubte that indicates that the associated + /// class does consider whitespace to be signifant. + /// + public WhitespaceSignificantCollectionAttribute() + { + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetMarkupExtensionAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetMarkupExtensionAttribute.cs new file mode 100644 index 00000000000..0e5e3904441 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetMarkupExtensionAttribute.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Globalization; + +namespace System.Windows.Markup +{ + [AttributeUsage(AttributeTargets.Class, Inherited=true, AllowMultiple=false)] + public sealed class XamlSetMarkupExtensionAttribute : Attribute + { + public XamlSetMarkupExtensionAttribute(string xamlSetMarkupExtensionHandler) + { + XamlSetMarkupExtensionHandler = xamlSetMarkupExtensionHandler; + } + + public String XamlSetMarkupExtensionHandler { get; private set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetMarkupExtensionEventArgs.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetMarkupExtensionEventArgs.cs new file mode 100644 index 00000000000..e178a8b1366 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetMarkupExtensionEventArgs.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Globalization; +using System.Xaml; + +namespace System.Windows.Markup +{ + public class XamlSetMarkupExtensionEventArgs : XamlSetValueEventArgs + { + public XamlSetMarkupExtensionEventArgs(XamlMember member, + MarkupExtension value, IServiceProvider serviceProvider) : + base(member, value) + { + ServiceProvider = serviceProvider; + } + + public MarkupExtension MarkupExtension { get { return Value as MarkupExtension; } } + public IServiceProvider ServiceProvider { get; private set; } + + internal XamlSetMarkupExtensionEventArgs(XamlMember member, + System.Windows.Markup.MarkupExtension value, IServiceProvider serviceProvider, Object targetObject) + : this(member, value, serviceProvider) + { + TargetObject = targetObject; + } + + internal XamlType CurrentType { get; set; } + internal Object TargetObject { get; private set; } + + public override void CallBase() + { + if (CurrentType != null) + { + XamlType baseType = CurrentType.BaseType; + + if (baseType != null) + { + this.CurrentType = baseType; + if (baseType.SetMarkupExtensionHandler != null) + { + baseType.SetMarkupExtensionHandler(TargetObject, this); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetTypeConverterAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetTypeConverterAttribute.cs new file mode 100644 index 00000000000..5f138c2e5b5 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetTypeConverterAttribute.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Globalization; + +namespace System.Windows.Markup +{ + [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)] + public sealed class XamlSetTypeConverterAttribute : Attribute + { + public XamlSetTypeConverterAttribute(string xamlSetTypeConverterHandler) + { + XamlSetTypeConverterHandler = xamlSetTypeConverterHandler; + } + + public string XamlSetTypeConverterHandler { get; private set; } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetTypeConverterEventArgs.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetTypeConverterEventArgs.cs new file mode 100644 index 00000000000..3c177f9dd16 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetTypeConverterEventArgs.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Globalization; +using System.Xaml; + +namespace System.Windows.Markup +{ + public class XamlSetTypeConverterEventArgs : XamlSetValueEventArgs + { + public XamlSetTypeConverterEventArgs(XamlMember member, TypeConverter typeConverter, object value, + ITypeDescriptorContext serviceProvider, CultureInfo cultureInfo) : + base(member, value) + { + TypeConverter = typeConverter; + ServiceProvider = serviceProvider; + CultureInfo = cultureInfo; + } + + internal XamlSetTypeConverterEventArgs(XamlMember member, TypeConverter typeConverter, object value, + ITypeDescriptorContext serviceProvider, CultureInfo cultureInfo, object targetObject) : + this(member, typeConverter, value, serviceProvider, cultureInfo) + { + TargetObject = targetObject; + } + + public TypeConverter TypeConverter { get; private set; } + public ITypeDescriptorContext ServiceProvider { get; private set; } + public CultureInfo CultureInfo { get; private set; } + + internal object TargetObject { get; private set; } + internal XamlType CurrentType { get; set; } + + public override void CallBase() + { + if (CurrentType != null) + { + XamlType baseType = CurrentType.BaseType; + + if (baseType != null) + { + this.CurrentType = baseType; + if (baseType.SetTypeConverterHandler != null) + { + baseType.SetTypeConverterHandler(TargetObject, this); + } + } + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetValueEventArgs.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetValueEventArgs.cs new file mode 100644 index 00000000000..a40905a6cf0 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XamlSetValueEventArgs.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Globalization; +using System.Xaml; + +namespace System.Windows.Markup +{ + public class XamlSetValueEventArgs : EventArgs + { + public XamlSetValueEventArgs(XamlMember member, object value) + { + Value = value; + Member = member; + } + + public XamlMember Member { get; private set; } + public object Value { get; private set; } + + public bool Handled { get; set; } + + public virtual void CallBase() + { + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlLangPropertyAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlLangPropertyAttribute.cs new file mode 100644 index 00000000000..234563e5eae --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlLangPropertyAttribute.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// +// Description: +// This attribute is placed on a class to identify it as the place to set +// the value of the xml:lang attribute from the XML markup file. +// +// Example: +// [XmlLangProperty("Language")] +// public class ExampleFrameworkElement +// +// Means that when the parser sees: +// +// +// +// The parser will set the "Language" property with the value "en-US". +// +// +// + +using System; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// An attribute that specifies which property the xml:lang value should + /// be directed to. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple=false)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class XmlLangPropertyAttribute : Attribute + { + /// + /// Creates a new XmlLangPropertyAttribute with the given string + /// as the property name. + /// + public XmlLangPropertyAttribute(string name) + { + _name = name; + } + + /// + /// The name of the property that is designated to accept the xml:lang value + /// + public string Name + { + get + { + return _name; + } + } + + // The name of the property that is designated to accept the xml:lang value + private string _name = null; + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlnsCompatibleWithAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlnsCompatibleWithAttribute.cs new file mode 100644 index 00000000000..b03037a4a00 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlnsCompatibleWithAttribute.cs @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Contents: Namespace compatiblity support + +using System; +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// + /// This attribute allows an assembly to declare that previously published + /// XmlnsDefinitions are subsumed by a new version. + /// + /// Such as + /// + /// "http://schemas.example.com/2003/mynamespace" + /// + /// is changed to + /// + /// "http://schemas.example.com/2005/mynamespace" + /// + /// + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class XmlnsCompatibleWithAttribute : Attribute + { + /// + /// Constructor + /// + /// old Xml namespce + /// new xml namespace + public XmlnsCompatibleWithAttribute(string oldNamespace, string newNamespace) + { + // Validate Input Arguments + if (oldNamespace == null) + { + throw new ArgumentNullException("oldNamespace"); + } + + if (newNamespace == null) + { + throw new ArgumentNullException("newNamespace"); + } + + _oldNamespace = oldNamespace; + _newNamespace = newNamespace; + } + + #region public properties + + /// + /// Old Xml Namespace + /// + public string OldNamespace + { + get { return _oldNamespace; } + } + + /// + /// New Xml Namespace + /// + public string NewNamespace + { + get { return _newNamespace; } + } + + #endregion public properties + + + #region Private Fields + + private string _oldNamespace; + private string _newNamespace; + + #endregion Private Fields + + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlnsDefinitionAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlnsDefinitionAttribute.cs new file mode 100644 index 00000000000..25a3f1209aa --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlnsDefinitionAttribute.cs @@ -0,0 +1,125 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Contents: Attribute that keep mapping between Xml namespace and +// the known types in assembly. + +using System; +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// + /// XmlnsDefinitionAttribute keeps a mapping between Xml namespace and CLR namespace in an Assembly. + /// The Xml namespace can be used in a Xaml Markup file. + /// + /// + /// To find the appropriate types for element and attribute in xaml file, xaml processors MUST + /// search each referenced assembly for XmlnsDefinitionAttribute. If the xmlns for element tag + /// or attribute matches with the XmlNamespace in this XmlnsDefinitionAttibute, the Xaml processor + /// then takes use of the ClrNamespace and AssemblyName stored in this Attibute instance to check + /// if the element or attribute matches any type inside this namespace in the Assembly. + /// + /// For a WinFX assembly, it can set this attibute like below: + /// + /// [assembly:XmlnsDefinition("http://schemas.fabrikam.com/mynamespace", "fabrikam.myproduct.mycategory1")] + /// [assembly:XmlnsDefinition("http://schemas.fabrikam.com/mynamespace", "fabrikam.myproduct.mycategory2")] + /// + /// [assembly:XmlnsDefinition("xmlnamsspace", "clrnamespace", AssemblyName="myassembly or full assemblyname")] + /// + /// If fabrikam.myproduct.mycategory namespace in this assembly contains a UIElement such as "MyButton", the + /// xaml file could use it like below: + /// + /// Page xmlns:myns="http://schemas.fabrikam.com/mynamespace" .... + /// myns:MyButton ...../myns:MyButton + /// /Page + /// + /// + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class XmlnsDefinitionAttribute: Attribute + { + /// + /// Constructor + /// + /// + /// XmlNamespace used by Markup file + /// + /// + /// Clr namespace which contains known types that are used by Markup File. + /// + public XmlnsDefinitionAttribute(string xmlNamespace, string clrNamespace) + { + // Validate Input Arguments + if (xmlNamespace == null) + { + throw new ArgumentNullException("xmlNamespace"); + } + + if (clrNamespace == null) + { + throw new ArgumentNullException("clrNamespace"); + } + + _xmlNamespace = xmlNamespace; + _clrNamespace = clrNamespace; + } + + #region public properties + + /// + /// XmlNamespace which can be used in Markup file. + /// such as XmlNamespace is set to + /// "http://schemas.fabrikam.com/mynamespace". + /// + /// The markup file can have definition like + /// xmlns:myns="http://schemas.fabrikam.com/mynamespace" + /// + /// + public string XmlNamespace + { + get { return _xmlNamespace; } + } + + /// + /// ClrNamespace which map to XmlNamespace. + /// This ClrNamespace should contain some types which are used + /// by Xaml markup file. + /// + public string ClrNamespace + { + get { return _clrNamespace; } + } + + /// + /// The name of Assembly that contains some types inside CLRNamespace. + /// If the assemblyName is not set, the code should take the assembly + /// for which the instance of this attribute is created. + /// + public string AssemblyName + { + get { return _assemblyName; } + set { _assemblyName = value; } + } + + #endregion public properties + + + #region Private Fields + + private string _xmlNamespace; + private string _clrNamespace; + private string _assemblyName; + + #endregion Private Fields + + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlnsPrefixAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlnsPrefixAttribute.cs new file mode 100644 index 00000000000..364ebc18a02 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/Markup/XmlnsPrefixAttribute.cs @@ -0,0 +1,97 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Microsoft Windows Client Platform +// +// +// Contents: Namespace default prefix recommendation support + +// Created: 04/28/2005 Microsoft +// + +using System; +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace System.Windows.Markup +{ + /// + /// + /// This attribute allows an assembly to recommend a prefix to be used when writing elements and + /// attributes in a xaml file. + /// + /// For a WinFX assembly, it can set the attributes as follows: + /// + /// + /// [assembly:XmlnsDefinition("http://schemas.fabrikam.com/mynamespace", "fabrikam.myproduct.mycategory1")] + /// [assembly:XmlnsDefinition("http://schemas.fabrikam.com/mynamespace", "fabrikam.myproduct.mycategory2")] + /// [assembly:XmlnsPrefix("http://schemas.fabrikam.com/mynamespace", "myns")] + /// + /// + /// If fabrikam.myproduct.mycategory namespace in this assembly contains a UIElement such as "MyButton", the + /// xaml file could use it like below: + /// + /// <Page xmlns:myns="http://schemas.fabrikam.com/mynamespace" .... > + /// <myns:MyButton> ..... </myns:MyButton> + /// </Page> + /// + /// + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + [TypeForwardedFrom("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public sealed class XmlnsPrefixAttribute : Attribute + { + /// + /// Constructor + /// + /// XML namespce + /// recommended prefix + public XmlnsPrefixAttribute(string xmlNamespace, string prefix) + { + // Validate Input Arguments + if (xmlNamespace == null) + { + throw new ArgumentNullException("xmlNamespace"); + } + + if (prefix == null) + { + throw new ArgumentNullException("prefix"); + } + + _xmlNamespace = xmlNamespace; + _prefix= prefix; + } + + #region public properties + + /// + /// XML Namespace + /// + public string XmlNamespace + { + get { return _xmlNamespace; } + } + + /// + /// New Xml Namespace + /// + public string Prefix + { + get { return _prefix; } + } + + #endregion public properties + + + #region Private Fields + + private string _xmlNamespace; + private string _prefix; + + #endregion Private Fields + + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/NameScope.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/NameScope.cs new file mode 100644 index 00000000000..422b5946838 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/NameScope.cs @@ -0,0 +1,390 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Used to store mapping information for names occuring +// within the logical tree section. + +using System; +using System.Windows; +using System.Collections; +using System.Collections.Specialized; +using System.Globalization; +using System.Windows.Markup; +using System.ComponentModel; +using System.Collections.Generic; +using MS.Internal; +using System.Runtime.CompilerServices; + +namespace System.Xaml +{ + /// + /// Used to store mapping information for names occuring + /// within the logical tree section. + /// + internal class NameScope : INameScopeDictionary + { + #region INameScope + + /// + /// Register Name-Object Map + /// + /// name to be registered + /// object mapped to name + public void RegisterName(string name, object scopedElement) + { + if (name == null) + throw new ArgumentNullException("name"); + + if (scopedElement == null) + throw new ArgumentNullException("scopedElement"); + + if (name == String.Empty) + throw new ArgumentException(SR.Get(SRID.NameScopeNameNotEmptyString)); + + if (!NameValidationHelper.IsValidIdentifierName(name)) + { + throw new ArgumentException(SR.Get(SRID.NameScopeInvalidIdentifierName, name)); + } + + if (_nameMap == null) + { + _nameMap = new HybridDictionary(); + _nameMap[name] = scopedElement; + } + else + { + object nameContext = _nameMap[name]; + // first time adding the Name, set it + if (nameContext == null) + { + _nameMap[name] = scopedElement; + } + else if (scopedElement != nameContext) + { + throw new ArgumentException(SR.Get(SRID.NameScopeDuplicateNamesNotAllowed, name)); + } + } + + //if( TraceNameScope.IsEnabled ) + //{ + // TraceNameScope.TraceActivityItem( TraceNameScope.RegisterName, + // this, + // name, + // scopedElement ); + //} + } + + /// + /// Unregister Name-Object Map + /// + /// name to be registered + public void UnregisterName(string name) + { + if (name == null) + throw new ArgumentNullException("name"); + + if (name == String.Empty) + throw new ArgumentException(SR.Get(SRID.NameScopeNameNotEmptyString)); + + if (_nameMap != null && _nameMap[name] != null) + { + _nameMap.Remove(name); + } + else + { + throw new ArgumentException(SR.Get(SRID.NameScopeNameNotFound, name)); + } + + //if( TraceNameScope.IsEnabled ) + //{ + // TraceNameScope.TraceActivityItem( TraceNameScope.UnregisterName, + // this, name ); + //} + } + + /// + /// Find - Find the corresponding object given a Name + /// + /// Name for which context needs to be retrieved + /// corresponding Context if found, else null + public object FindName(string name) + { + if (_nameMap == null || name == null || name == String.Empty) + return null; + + return _nameMap[name]; + } + + #endregion INameScope + + #region Data + + // This is a HybridDictionary of Name-Object maps + private HybridDictionary _nameMap; + + #endregion Data + + IEnumerator> GetEnumerator() + { + return new Enumerator(this._nameMap); + } + + #region IEnumerable methods + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + #endregion + + #region IEnumerable methods + IEnumerator> IEnumerable>.GetEnumerator() + { + return this.GetEnumerator(); + } + #endregion + + #region ICollection methods + public int Count + { + get + { + if (_nameMap == null) + { + return 0; + } + return _nameMap.Count; + } + } + + public bool IsReadOnly + { + get + { + return false; + } + } + + public void Clear() + { + _nameMap = null; + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + if (_nameMap == null) + { + array = null; + return; + } + + foreach (DictionaryEntry entry in _nameMap) + { + array[arrayIndex++] = new KeyValuePair((string)entry.Key, entry.Value); + } + } + + public bool Remove(KeyValuePair item) + { + if (!Contains(item)) + { + return false; + } + + if (item.Value != this[item.Key]) + { + return false; + } + return Remove(item.Key); + } + + public void Add(KeyValuePair item) + { + if (item.Key == null) + { + throw new ArgumentException(SR.Get(SRID.ReferenceIsNull, "item.Key"), "item"); + } + if (item.Value == null) + { + throw new ArgumentException(SR.Get(SRID.ReferenceIsNull, "item.Value"), "item"); + } + + Add(item.Key, item.Value); + } + + public bool Contains(KeyValuePair item) + { + if (item.Key == null) + { + throw new ArgumentException(SR.Get(SRID.ReferenceIsNull, "item.Key"), "item"); + } + return ContainsKey(item.Key); + } + #endregion + + #region IDictionary methods + public object this[string key] + { + get + { + if (key == null) + { + throw new ArgumentNullException("key"); + } + return FindName(key); + } + set + { + if (key == null) + { + throw new ArgumentNullException("key"); + } + + if (value == null) + { + throw new ArgumentNullException("value"); + } + + RegisterName(key, value); + } + } + + public void Add(string key, object value) + { + if (key == null) + { + throw new ArgumentNullException("key"); + } + + RegisterName(key, value); + } + + public bool ContainsKey(string key) + { + if (key == null) + { + throw new ArgumentNullException("key"); + } + + object value = FindName(key); + return (value != null); + } + + public bool Remove(string key) + { + if (!ContainsKey(key)) + { + return false; + } + UnregisterName(key); + return true; + } + + public bool TryGetValue(string key, out object value) + { + if (!ContainsKey(key)) + { + value = null; + return false; + } + value = FindName(key); + return true; + } + + public ICollection Keys + { + get + { + if (_nameMap == null) + { + return null; + } + + var list = new List(); + foreach (string key in _nameMap.Keys) + { + list.Add(key); + } + return list; + } + } + + public ICollection Values + { + get + { + if (_nameMap == null) + { + return null; + } + + var list = new List(); + foreach (object value in _nameMap.Values) + { + list.Add(value); + } + return list; + } + } + #endregion + + #region class Enumerator + class Enumerator : IEnumerator> + { + IDictionaryEnumerator _enumerator; + + public Enumerator(HybridDictionary nameMap) + { + _enumerator = null; + + if (nameMap != null) + { + _enumerator = nameMap.GetEnumerator(); + } + } + + public void Dispose() + { + GC.SuppressFinalize(this); + } + + public KeyValuePair Current + { + get + { + if (_enumerator == null) + { + return default(KeyValuePair); + } + return new KeyValuePair((string)_enumerator.Key, _enumerator.Value); + } + } + + public bool MoveNext() + { + if (_enumerator == null) + { + return false; + } + return _enumerator.MoveNext(); + } + + object IEnumerator.Current + { + get + { + return this.Current; + } + } + + void IEnumerator.Reset() + { + if (_enumerator != null) + { + _enumerator.Reset(); + } + } + } + #endregion + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/NameValidationHelper.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/NameValidationHelper.cs new file mode 100644 index 00000000000..48449bfbcaa --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Windows/NameValidationHelper.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Used to store mapping information for names occuring +// within the logical tree section. + +using System; +using System.Globalization; + + +namespace System.Xaml +{ + /// + /// The string used in RuntimeNameProperty is expected to follow certain + /// rules. IsValidIdentifierName checks the given string against the rules. + /// NameValidationCallback extends to all object types and is in the right + /// format to be used as a DependencyProperty ValidateValueCallback + /// + internal static class NameValidationHelper + { + /// + /// Validates the name to follow Naming guidelines + /// + /// string to validate + internal static bool IsValidIdentifierName(string name) + { + // Grammar: + // ::= ( | )* + // ::= [{Lu}{Ll}{Lt}{Lo}{Nl}('_')] + // ::= [{Mn}{Mc}{Lm}{Nd}] + UnicodeCategory uc; + for (int i = 0; i < name.Length; i++) + { + uc = Char.GetUnicodeCategory(name[i]); + bool idStart = (uc == UnicodeCategory.UppercaseLetter || // (Lu) + uc == UnicodeCategory.LowercaseLetter || // (Ll) + uc == UnicodeCategory.TitlecaseLetter || // (Lt) + uc == UnicodeCategory.OtherLetter || // (Lo) + uc == UnicodeCategory.LetterNumber || // (Nl) + name[i] == '_'); + bool idExtend = (uc == UnicodeCategory.NonSpacingMark || // (Mn) + uc == UnicodeCategory.SpacingCombiningMark || // (Mc) + uc == UnicodeCategory.ModifierLetter || // (Lm) + uc == UnicodeCategory.DecimalDigitNumber); // (Nd) + if (i == 0) + { + if (!idStart) + { + return false; + } + } + else if (!(idStart || idExtend)) + { + return false; + } + } + return true; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/AllowedMemberLocations.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/AllowedMemberLocations.cs new file mode 100644 index 00000000000..bd15d8d116a --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/AllowedMemberLocations.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; + +using System.Text; + +namespace System.Xaml.Schema +{ + [Flags] + public enum AllowedMemberLocations + { + None = 0, + Attribute = 1, + MemberElement = 2, + Any = Attribute | MemberElement, + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/AttachableMemberIdentifier.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/AttachableMemberIdentifier.cs new file mode 100644 index 00000000000..85c9e6cf347 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/AttachableMemberIdentifier.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Xaml +{ + using System; + + public class AttachableMemberIdentifier : IEquatable + { + Type declaringType; + string memberName; + + public AttachableMemberIdentifier(Type declaringType, string memberName) + { + this.declaringType = declaringType; + this.memberName = memberName; + } + + public string MemberName + { + get + { + return memberName; + } + } + + public Type DeclaringType + { + get + { + return this.declaringType; + } + } + + public static bool operator !=(AttachableMemberIdentifier left, AttachableMemberIdentifier right) + { + return !(left == right); + } + + public static bool operator ==(AttachableMemberIdentifier left, AttachableMemberIdentifier right) + { + if (object.ReferenceEquals(left, null)) + { + return object.ReferenceEquals(right, null); + } + return left.Equals(right); + } + + public override bool Equals(object obj) + { + return Equals(obj as AttachableMemberIdentifier); + } + + public bool Equals(AttachableMemberIdentifier other) + { + if (other == null) + { + return false; + } + + return this.declaringType == other.declaringType && this.memberName == other.memberName; + } + + public override int GetHashCode() + { + int a = this.declaringType == null ? 0 : this.declaringType.GetHashCode(); + int b = this.memberName == null ? 0 : this.memberName.GetHashCode(); + return ((a << 5) + a) ^ b; + } + + public override string ToString() + { + if (this.declaringType == null) + { + return this.memberName; + } + + return this.declaringType.ToString() + "." + memberName; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/AttachablePropertyServices.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/AttachablePropertyServices.cs new file mode 100644 index 00000000000..90dd6471ecf --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/AttachablePropertyServices.cs @@ -0,0 +1,554 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Xaml +{ + using System.Collections.Generic; + using System.Reflection; + using System.Threading; + using System.Windows; + using System.Diagnostics.CodeAnalysis; + using System.Runtime.CompilerServices; + + public static class AttachablePropertyServices + { + static DefaultAttachedPropertyStore attachedProperties = new DefaultAttachedPropertyStore(); + + public static int GetAttachedPropertyCount(object instance) + { + if (instance == null) + { + return 0; + } + + IAttachedPropertyStore ap = instance as IAttachedPropertyStore; + if (ap != null) + { + return ap.PropertyCount; + } + + return attachedProperties.GetPropertyCount(instance); + } + + public static void CopyPropertiesTo(object instance, KeyValuePair[] array, int index) + { + if (instance == null) + { + return; + } + + IAttachedPropertyStore ap = instance as IAttachedPropertyStore; + if (ap != null) + { + ap.CopyPropertiesTo(array, index); + } + else + { + attachedProperties.CopyPropertiesTo(instance, array, index); + } + } + + public static bool RemoveProperty(object instance, AttachableMemberIdentifier name) + { + if (instance == null) + { + return false; + } + + IAttachedPropertyStore ap = instance as IAttachedPropertyStore; + if (ap != null) + { + return ap.RemoveProperty(name); + } + + return attachedProperties.RemoveProperty(instance, name); + } + + public static void SetProperty(object instance, AttachableMemberIdentifier name, object value) + { + if (instance == null) + { + return; + } + + if (name == null) + { + throw new ArgumentNullException("name"); + } + + IAttachedPropertyStore ap = instance as IAttachedPropertyStore; + if (ap != null) + { + ap.SetProperty(name, value); + return; + } + + attachedProperties.SetProperty(instance, name, value); + } + + [SuppressMessage("Microsoft.Design", "CA1007")] + public static bool TryGetProperty(object instance, AttachableMemberIdentifier name, out object value) + { + return TryGetProperty(instance, name, out value); + } + + public static bool TryGetProperty(object instance, AttachableMemberIdentifier name, out T value) + { + if (instance == null) + { + value = default(T); + return false; + } + + IAttachedPropertyStore ap = instance as IAttachedPropertyStore; + if (ap != null) + { + object obj; + bool result = ap.TryGetProperty(name, out obj); + if (result) + { + if (obj is T) + { + value = (T)obj; + return true; + } + } + value = default(T); + return false; + } + + return attachedProperties.TryGetProperty(instance, name, out value); + } + + // DefaultAttachedPropertyStore is used by the global AttachedPropertyServices to implement + // global attached properties for types which don't implement IAttachedProperties or DO/Dependency Property + // integration for their attached properties. + // + #if !TARGETTING35SP1 + sealed class DefaultAttachedPropertyStore + { + Lazy>> instanceStorage = + new Lazy>>(); + + public void CopyPropertiesTo(object instance, KeyValuePair[] array, int index) + { + if (instanceStorage.IsValueCreated) + { + Dictionary instanceProperties; + if (instanceStorage.Value.TryGetValue(instance, out instanceProperties)) + { + lock (instanceProperties) + { + ((ICollection>)instanceProperties).CopyTo(array, index); + } + } + } + } + + public int GetPropertyCount(object instance) + { + if (instanceStorage.IsValueCreated) + { + Dictionary instanceProperties; + if (instanceStorage.Value.TryGetValue(instance, out instanceProperties)) + { + lock (instanceProperties) + { + return instanceProperties.Count; + } + } + } + return 0; + } + + // + // Remove the property 'name'. If the property doesn't exist it returns false. + // + public bool RemoveProperty(object instance, AttachableMemberIdentifier name) + { + if (instanceStorage.IsValueCreated) + { + Dictionary instanceProperties; + if (instanceStorage.Value.TryGetValue(instance, out instanceProperties)) + { + lock (instanceProperties) + { + return instanceProperties.Remove(name); + } + } + } + return false; + } + + // + // Set the property 'name' value to 'value', if the property doesn't currently exist this will add the property + // + public void SetProperty(object instance, AttachableMemberIdentifier name, object value) + { + Dictionary instanceProperties; + if (!instanceStorage.Value.TryGetValue(instance, out instanceProperties)) + { + instanceProperties = new Dictionary(); + // + // Workaround lack of TryAdd for ConditionalWeakTable + try + { + instanceStorage.Value.Add(instance, instanceProperties); + } + catch (ArgumentException) + { + // + // If Add fails we raced and the item should exist + if (!instanceStorage.Value.TryGetValue(instanceStorage, out instanceProperties)) + { + // + // If for some reason it doesn't, throw. + throw new InvalidOperationException(SR.Get(SRID.DefaultAttachablePropertyStoreCannotAddInstance)); + } + } + } + + lock (instanceProperties) + { + instanceProperties[name] = value; + } + } + + // + // Retrieve the value of the attached property 'name'. If there is not attached property then return false. + // + public bool TryGetProperty(object instance, AttachableMemberIdentifier name, out T value) + { + if (instanceStorage.IsValueCreated) + { + Dictionary instanceProperties; + if (instanceStorage.Value.TryGetValue(instance, out instanceProperties)) + { + lock (instanceProperties) + { + object valueAsObj; + if (instanceProperties.TryGetValue(name, out valueAsObj) && + valueAsObj is T) + { + value = (T)valueAsObj; + return true; + } + } + } + } + value = default(T); + return false; + } + } +#else + //***********************************************WARNING************************************************************ + // In CLR4.0 there is ConditionalWeakTable. This implementation is for 3.5 and uses a WeakKey dictionary. + // This implementation does not handle the problem where a key is rooted in a value (or graph of a value). + // This will "leak" (never get cleaned up). If we ship a 3.5 version of System.Xaml.dll we should + // consider adding logic that detects such cycles on Add and throws. + //****************************************************************************************************************** + sealed class DefaultAttachedPropertyStore + { + Lazy>> instanceStorage = + new Lazy>>( + () => new WeakDictionary>(), LazyInitMode.AllowMultipleThreadSafeExecution); + + public void CopyPropertiesTo(object instance, KeyValuePair[] array, int index) + { + if (instanceStorage.IsInitialized) + { + lock (instanceStorage.Value.SyncObject) + { + Dictionary instanceProperties; + if (instanceStorage.Value.TryGetValue(instance, out instanceProperties)) + { + ((ICollection>)instanceProperties).CopyTo(array, index); + } + } + } + } + + public int GetPropertyCount(object instance) + { + if (instanceStorage.IsInitialized) + { + lock(instanceStorage.Value.SyncObject) + { + Dictionary instanceProperties; + if (instanceStorage.Value.TryGetValue(instance, out instanceProperties)) + { + return instanceProperties.Count; + } + } + } + return 0; + } + + // + // Remove the property 'name'. If the property doesn't exist it returns false. + // + public bool RemoveProperty(object instance, AttachableMemberIdentifier name) + { + if (instanceStorage.IsInitialized) + { + lock (instanceStorage.Value.SyncObject) + { + Dictionary instanceProperties; + if (instanceStorage.Value.TryGetValue(instance, out instanceProperties)) + { + return instanceProperties.Remove(name); + } + } + } + return false; + } + + // + // Set the property 'name' value to 'value', if the property doesn't currently exist this will add the property + // + public void SetProperty(object instance, AttachableMemberIdentifier name, object value) + { + // + // Accessing Value forces initialization + lock (instanceStorage.Value.SyncObject) + { + Dictionary instanceProperties; + if (!instanceStorage.Value.TryGetValue(instance, out instanceProperties)) + { + instanceProperties = new Dictionary(); + instanceStorage.Value.Add(instance, instanceProperties); + } + instanceProperties[name] = value; + } + } + + // + // Retrieve the value of the attached property 'name'. If there is not attached property then return false. + // + public bool TryGetProperty(object instance, AttachableMemberIdentifier name, out T value) + { + if (instanceStorage.IsInitialized) + { + lock (instanceStorage.Value.SyncObject) + { + Dictionary attachedProperties; + if (instanceStorage.Value.TryGetValue(instance, out attachedProperties)) + { + object valueAsObj; + if (attachedProperties.TryGetValue(name, out valueAsObj) && + valueAsObj is T) + { + value = (T)valueAsObj; + return true; + } + } + } + } + value = default(T); + return false; + } + + public class WeakDictionary + where K : class + where V : class + { + // Optimally this would be a _real_ dictionary implementation that when it ran across WeakKey's that had + // gone out of scope would immediately at least clear their value and from time to time schedule a real + // cleanup. + Dictionary storage; + object cleanupSyncObject; + + public WeakDictionary() + { + if (typeof(K) == typeof(WeakReference)) + { + throw new InvalidOperationException(); + } + + this.cleanupSyncObject = new object(); + storage = new Dictionary.WeakKey, V>(); + // kick off the cleanup process... + WeakDictionaryCleanupToken.CreateCleanupToken(this); + } + + public int Count + { + get { return storage.Count; } + } + + public void Add(K key, V value) + { + storage.Add(new WeakKey(key, false), value); + } + + internal object SyncObject + { + get { return this.cleanupSyncObject; } + } + + public void Cleanup() + { + List toClean = null; + + // First determine what items have died and can be removed... + lock(cleanupSyncObject) + { + foreach (var key in storage.Keys) + { + bool isAlive, needsCleanup; + key.GetValue(out isAlive, out needsCleanup); + if (!isAlive) + { + if (toClean == null) + { + toClean = new List(); + } + toClean.Add(key); + } + } + } + + if (toClean != null) + { + // Second go and remove them... + lock(cleanupSyncObject) + { + // If toClean is > some % of the total size it is probably better + // just to create a new dictionary and migrate some set of items over + // wholesale? It is unclear whether or not this is true. + foreach (var key in toClean) + { + storage.Remove(key); + } + } + } + + WeakDictionaryCleanupToken.CreateCleanupToken(this); + } + + public bool Remove(K key) + { + return storage.Remove(new WeakKey(key, true)); + } + + public bool TryGetValue(K key, out V value) + { + return storage.TryGetValue(new WeakKey(key, true), out value); + } + + public struct WeakKey : IEquatable + { + int hashCode; + object reference; + + public WeakKey(K key, bool lookup) + { + hashCode = key.GetHashCode(); + reference = lookup ? key : (object)new WeakReference(key); + } + + public override int GetHashCode() + { + return hashCode; + } + + public K GetValue(out bool isAlive, out bool needsCleanup) + { + if (reference == null) + { + isAlive = false; + needsCleanup = false; + return (K)reference; + } + + K value; + WeakReference wr = reference as WeakReference; + if (wr != null) + { + value = (K)wr.Target; + isAlive = value != null; + needsCleanup = !isAlive; + if (needsCleanup) + { + // This cleans up the WeakReference now that we know the + // target object is dead... + reference = null; + } + return value; + } + + value = reference as K; + if (value != null) + { + isAlive = true; + needsCleanup = false; + return value; + } + + throw new InvalidOperationException(); + } + + public bool Equals(WeakKey other) + { + WeakKey x = this; + WeakKey y = other; + bool xIsAlive, yIsAlive; + bool xNeedsCleanup, yNeedsCleanup; + K xKey = x.GetValue(out xIsAlive, out xNeedsCleanup); + K yKey = y.GetValue(out yIsAlive, out yNeedsCleanup); + + // If they are both not alive then they are equivalent + if (!xIsAlive && !yIsAlive) + { + return true; + } + + if (!xIsAlive || !yIsAlive) + { + return false; + } + + return xKey == yKey; + } + } + + // This cleanup token will be immediately thrown away and as a result it will + // (a couple of GCs later) make it into the finalization queue and when finalized + // will kick off a thread-pool job to cleanup the dictionary. + + public class WeakDictionaryCleanupToken + { + WeakDictionary storage; + + WeakDictionaryCleanupToken(WeakDictionary storage) + { + this.storage = storage; + } + + ~WeakDictionaryCleanupToken() + { + // Schedule cleanup + ThreadPool.QueueUserWorkItem((WaitCallback)delegate + { + storage.Cleanup(); + }); + } + + [SuppressMessage("Microsoft.Usage", "CA1806", + Justification = "The point of this method is to create one of these and let it float away... To be finalized...")] + [SuppressMessage("Microsoft.Performance", "CA1804", + Justification = "The point of this method is to create one of these and let it float away... To be finalized...")] + public static void CreateCleanupToken(WeakDictionary storage) + { + // Create one of these, the work is done when it is finalized which + // will be at some indeterminate point in the future... + WeakDictionaryCleanupToken token = new WeakDictionaryCleanupToken(storage); + } + } + + } + } +#endif + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ContextServices.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ContextServices.cs new file mode 100644 index 00000000000..8d4908dd8f8 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ContextServices.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Xaml; +using System.Xaml.Schema; +using System.Xaml.MS.Impl; +using System.Windows; +using System.Diagnostics; + + +namespace MS.Internal.Xaml.Context +{ + internal static class ContextServices + { + // Used to implement IProvideValueTarget Service provider. + public static object GetTargetProperty(ObjectWriterContext xamlContext) + { + // If the XamlMember implements IProvideValueTarget, ask it for the TargetProperty first + Debug.Assert(xamlContext.ParentProperty != null); + + System.Windows.Markup.IProvideValueTarget ipvt = xamlContext.ParentProperty as System.Windows.Markup.IProvideValueTarget; + if (ipvt != null) + { + return ipvt.TargetProperty; + } + + XamlMember parentProperty = xamlContext.ParentProperty; + // + // We should never have a null ParentProperty here but + // protect against null refs since we are going to dereference it + if (parentProperty == null) + { + return null; + } + + if (parentProperty.IsAttachable) + { + // + // IPVT returns the static Set method for attached properties in 3.0 + return parentProperty.Setter; + } + else + { + // + // This branch cover regular property (will return non null) + // and items in a collection/diction (will return null - IPVT returns null in 3.0 for collections/dictionaries). + return parentProperty.UnderlyingMember; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/HashSet.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/HashSet.cs new file mode 100644 index 00000000000..84b9cc97d9e --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/HashSet.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; + +namespace System.Xaml.Context +{ + internal class HashSet : Dictionary + { + public HashSet() + : base() + { + } + + public HashSet(IDictionary other) + : base(other) + { + } + + public HashSet(IEqualityComparer comparer) + : base(comparer) + { + } + + public void Add(T item) + { + Add(item, null); + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ICheckIfInitialized.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ICheckIfInitialized.cs new file mode 100644 index 00000000000..92390817159 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ICheckIfInitialized.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MS.Internal.Xaml.Context +{ + // This interface allows ObjectWriterContext to call into ObjectWriter to get the live initialization + // status of an object. We direct calls through this interface to avoid breaking our internal layering + // by having a direct reference from ObjectWriterContext to ObjectWriter. + internal interface ICheckIfInitialized + { + bool IsFullyInitialized(object obj); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/NameFixupGraph.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/NameFixupGraph.cs new file mode 100644 index 00000000000..c1ca72743d4 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/NameFixupGraph.cs @@ -0,0 +1,502 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Text; +using System.Windows.Markup; +using System.Xaml; +using System.Xaml.MS.Impl; + +namespace MS.Internal.Xaml.Context +{ + // Graph of unresolved forward references, and the objects that depend on them. + // The nodes are objects and names. The edges (NameFixupTokens) are dependencies from an object to + // a set of unresolved names, or from an object to another object that has unresolved dependencies. + internal class NameFixupGraph + { + // Node -> out-edges (other objects the parent is dependent on) + Dictionary> _dependenciesByParentObject; + + // Node -> in-edge (other object that is dependent on this child) + Dictionary _dependenciesByChildObject; + + // Node -> in-edges (other objects that are dependent on this name) + Dictionary> _dependenciesByName; + + // Queue of tokens whose dependencies have been resolved, and are awaiting processing + Queue _resolvedTokensPendingProcessing; + + // Token for a pending call to ProvideValue on the root object. Can't store this in + // _dependenciesByParentObject because it has no parent. + NameFixupToken _deferredRootProvideValue; + + // At the end of the parse, we start running reparses on partially initialized objects, + // and remove those dependencies. But we still want to be able to inform MEs/TCs that + // the named objects they're getting aren't actually fully initialized. So we save this list + // of incompletely initialized objects at the point we start completing references. + HashSet _uninitializedObjectsAtParseEnd; + + public NameFixupGraph() + { + var referenceComparer = System.Xaml.Schema.ReferenceEqualityComparer.Singleton; + _dependenciesByChildObject = new Dictionary(referenceComparer); + _dependenciesByName = new Dictionary>(StringComparer.Ordinal); + _dependenciesByParentObject = new Dictionary>(referenceComparer); + _resolvedTokensPendingProcessing = new Queue(); + _uninitializedObjectsAtParseEnd = new HashSet(referenceComparer); + } + + // Add an edge to the graph. We need to look up edges in both directions, so each edge is + // stored in two dictionaries. + public void AddDependency(NameFixupToken fixupToken) + { + // Need to special case a deferred ProvideValue at the root, because it has no parent + if (fixupToken.Target.Property == null) + { + Debug.Assert(fixupToken.Target.Instance == null && + fixupToken.Target.InstanceType == null && + fixupToken.FixupType == FixupType.MarkupExtensionFirstRun); + Debug.Assert(_deferredRootProvideValue == null); + _deferredRootProvideValue = fixupToken; + return; + } + + object parentObject = fixupToken.Target.Instance; + // References aren't allowed in non-instantiating directives, except for: + // - Initialization, in which case FixupTarget.Instance is the object whose property the + // initialized object will be assigned to; and + // - Key, in which case the FixupTarget.Instance is the dictionary + Debug.Assert(parentObject != null); + + AddToMultiDict(_dependenciesByParentObject, parentObject, fixupToken); + + if (fixupToken.ReferencedObject != null) + { + Debug.Assert(fixupToken.FixupType == FixupType.UnresolvedChildren || + fixupToken.FixupType == FixupType.MarkupExtensionFirstRun); + // These fixups are only used for the immediate parent of the object, so there can + // only be one per child instance + Debug.Assert(!_dependenciesByChildObject.ContainsKey(fixupToken.ReferencedObject)); + + _dependenciesByChildObject.Add(fixupToken.ReferencedObject, fixupToken); + } + else + { + Debug.Assert(fixupToken.FixupType != FixupType.UnresolvedChildren && + fixupToken.FixupType != FixupType.MarkupExtensionFirstRun); + + foreach (string name in fixupToken.NeededNames) + { + AddToMultiDict(_dependenciesByName, name, fixupToken); + } + } + } + + public bool HasUnresolvedChildren(object parent) + { + if (parent == null) + { + return false; + } + return _dependenciesByParentObject.ContainsKey(parent); + } + + public bool HasUnresolvedOrPendingChildren(object instance) + { + if (HasUnresolvedChildren(instance)) + { + return true; + } + foreach (NameFixupToken pendingToken in _resolvedTokensPendingProcessing) + { + if (pendingToken.Target.Instance == instance) + { + return true; + } + } + return false; + } + + public bool WasUninitializedAtEndOfParse(object instance) + { + return _uninitializedObjectsAtParseEnd.Contains(instance); + } + + // Finds the names that this object's subtree is blocked on. + public void GetDependentNames(object instance, List result) + { + // We're only interested in the immediate subtree, not named-references to other subtrees + // that might exist but not be fully initialized. So we only follow UnresolvedChildren and + // MarkupExtensionFirstRun edges, which means there is no risk of cycles + FrugalObjectList dependencies; + if (!_dependenciesByParentObject.TryGetValue(instance, out dependencies)) + { + return; + } + for (int i = 0; i < dependencies.Count; i++) + { + NameFixupToken token = dependencies[i]; + if (token.FixupType == FixupType.MarkupExtensionFirstRun || + token.FixupType == FixupType.UnresolvedChildren) + { + GetDependentNames(token.ReferencedObject, result); + } + else if (token.NeededNames != null) + { + foreach (string name in token.NeededNames) + { + if (!result.Contains(name)) + { + result.Add(name); + } + } + } + } + } + + // Remove a resolved dependency from the graph. + // Enqueues all removed edges so that the ObjectWriter can process the dependents + // (rerun converters, apply simple fixups, call EndInit on parent ojects, etc). + public void ResolveDependenciesTo(object instance, string name) + { + // Remove any dependency on this instance + NameFixupToken token = null; + if (instance != null) + { + if (_dependenciesByChildObject.TryGetValue(instance, out token)) + { + _dependenciesByChildObject.Remove(instance); + RemoveTokenByParent(token); + _resolvedTokensPendingProcessing.Enqueue(token); + } + } + + // Remove any dependencies on this name, and return any tokens whose dependencies + // have all been resolved. + FrugalObjectList nameDependencies; + if (name != null && _dependenciesByName.TryGetValue(name, out nameDependencies)) + { + int i = 0; + while (i < nameDependencies.Count) + { + token = nameDependencies[i]; + + // The same name can occur in multiple namescopes, so we need to make sure that + // this named object is visible in the scope of the token. + object resolvedName = token.ResolveName(name); + if (instance != resolvedName) + { + i++; + continue; + } + + if (token.CanAssignDirectly) + { + // For simple fixups, we need to return the resolved object + token.ReferencedObject = instance; + } + token.NeededNames.Remove(name); + nameDependencies.RemoveAt(i); + if (nameDependencies.Count == 0) + { + _dependenciesByName.Remove(name); + } + if (token.NeededNames.Count == 0) + { + RemoveTokenByParent(token); + _resolvedTokensPendingProcessing.Enqueue(token); + } + } + } + } + + public bool HasResolvedTokensPendingProcessing + { + get { return _resolvedTokensPendingProcessing.Count > 0; } + } + + public NameFixupToken GetNextResolvedTokenPendingProcessing() + { + return _resolvedTokensPendingProcessing.Dequeue(); + } + + // ObjectWriter calls this whenever an object that has pending fixups goes off the stack. + public void IsOffTheStack(object instance, string name, int lineNumber, int linePosition) + { + FrugalObjectList dependencies; + if (_dependenciesByParentObject.TryGetValue(instance, out dependencies)) + { + for (int i = 0; i < dependencies.Count; i++) + { + dependencies[i].Target.InstanceIsOnTheStack = false; + dependencies[i].Target.InstanceName = name; + dependencies[i].Target.EndInstanceLineNumber = lineNumber; + dependencies[i].Target.EndInstanceLinePosition = linePosition; + } + } + } + + public void AddEndOfParseDependency(object childThatHasUnresolvedChildren, FixupTarget parentObject) + { + NameFixupToken token = new NameFixupToken(); + token.Target = parentObject; + token.FixupType = FixupType.UnresolvedChildren; + token.ReferencedObject = childThatHasUnresolvedChildren; + AddToMultiDict(_dependenciesByParentObject, parentObject.Instance, token); + // We don't add to the _dependenciesByChildObject, because at end-of-parse, a single + // child object can be a dependency of multiple parents + } + + // At end of parse, removes and returns all remaining simple fixups, whether or not they + // are resolved + public IEnumerable GetRemainingSimpleFixups() + { + foreach (object key in _dependenciesByParentObject.Keys) + { + _uninitializedObjectsAtParseEnd.Add(key); + } + + List names = new List(_dependenciesByName.Keys); + foreach (string name in names) + { + FrugalObjectList dependencies = _dependenciesByName[name]; + int i = 0; + while (i < dependencies.Count) + { + NameFixupToken token = dependencies[i]; + if (!token.CanAssignDirectly) + { + i++; + continue; + } + dependencies.RemoveAt(i); + if (dependencies.Count == 0) + { + _dependenciesByName.Remove(name); + } + RemoveTokenByParent(token); + yield return token; + } + } + } + + // At end of parse, removes and returns all remaining reparse fixups, whether or not they + // are resolved. Assumes that all simple fixups have already been removed. + public IEnumerable GetRemainingReparses() + { + List parentObjs = new List(_dependenciesByParentObject.Keys); + foreach (object parentObj in parentObjs) + { + FrugalObjectList dependencies = _dependenciesByParentObject[parentObj]; + int i = 0; + while (i < dependencies.Count) + { + NameFixupToken token = dependencies[i]; + if (token.FixupType == FixupType.MarkupExtensionFirstRun || + token.FixupType == FixupType.UnresolvedChildren) + { + i++; + continue; + } + + // Remove this token from the _dependenciesByParentObject dictionary + dependencies.RemoveAt(i); + if (dependencies.Count == 0) + { + _dependenciesByParentObject.Remove(parentObj); + } + + // Remove this token from the _dependenciesByName dictionary + foreach (string name in token.NeededNames) + { + FrugalObjectList nameDependencies = _dependenciesByName[name]; + if (nameDependencies.Count == 1) + { + nameDependencies.Remove(token); + } + else + { + _dependenciesByName.Remove(name); + } + } + + yield return token; + } + } + } + + // At end of parse, removes and returns all remaining MarkupExtensionFirstRun and UnresolvedChildren + // tokens, even if they are not fully initialized. Assumes that all simple fixups and reparses have + // already been removed. + public IEnumerable GetRemainingObjectDependencies() + { + // We'd like to return dependencies in a topologically sorted order, but the graph is + // not acylic. (If it were, all references would have been resolved during the regular parse.) + // However, we don't allow ProvideValue cycles. So find a MarkupExtension that doesn't have + // dependencies on any other MarkupExtension. + + // Note: at this point we can't use _dependenciesByChildObject for general traversal, + // because it's not updated by AddEndOfParseDependency. However, AddEndOfParseDependency + // doesn't add MarkupExtension edges, so we can still use _dependenciesByChildObject for that. + List markupExtensionTokens = new List(); + foreach (NameFixupToken curToken in _dependenciesByChildObject.Values) + { + if (curToken.FixupType == FixupType.MarkupExtensionFirstRun) + { + markupExtensionTokens.Add(curToken); + } + } + while (markupExtensionTokens.Count > 0) + { + bool found = false; + int i = 0; + while (i < markupExtensionTokens.Count) + { + NameFixupToken meToken = markupExtensionTokens[i]; + List dependencies = new List(); + if (!FindDependencies(meToken, dependencies)) + { + i++; + continue; + } + // Iterate the list in backwards order, so we return the deepest first + for (int j = dependencies.Count - 1; j >= 0; j--) + { + NameFixupToken token = dependencies[j]; + RemoveTokenByParent(token); + yield return token; + } + found = true; + markupExtensionTokens.RemoveAt(i); + } + if (!found) + { + // We have MEs left, but they all have dependencies on other MEs. + // That means we have a cycle. + ThrowProvideValueCycle(markupExtensionTokens); + } + } + + // For the remaining EndInits, we pick an arbitrary point and return a DFS of its dependencies + while (_dependenciesByParentObject.Count > 0) + { + FrugalObjectList startNodeOutEdges = null; + foreach (FrugalObjectList list in _dependenciesByParentObject.Values) + { + startNodeOutEdges = list; + break; + } + for (int i = 0; i < startNodeOutEdges.Count; i++) + { + List dependencies = new List(); + FindDependencies(startNodeOutEdges[i], dependencies); + // Iterate the list in backwards order, so we return the deepest first + for (int j = dependencies.Count - 1; j >= 0; j--) + { + NameFixupToken token = dependencies[j]; + RemoveTokenByParent(token); + yield return token; + } + } + } + + // Finally, if there was a deferred ProvideValue at the root, return it + if (_deferredRootProvideValue != null) + { + yield return _deferredRootProvideValue; + } + } + + // Depth-first traversal of the graph starting at a given edge. Ignores edges that would cause cycles. + // Returns true if the dependency list is complete, false if we aborted because we found an ME. + private bool FindDependencies(NameFixupToken inEdge, List alreadyTraversed) + { + if (alreadyTraversed.Contains(inEdge)) + { + // Cycle, skip it + return true; + } + alreadyTraversed.Add(inEdge); + FrugalObjectList outEdges; + if (inEdge.ReferencedObject == null || + !_dependenciesByParentObject.TryGetValue(inEdge.ReferencedObject, out outEdges)) + { + // No dependencies, we're done with this subgraph + return true; + } + for (int i = 0; i < outEdges.Count; i++) + { + NameFixupToken outEdge = outEdges[i]; + if (outEdge.FixupType == FixupType.MarkupExtensionFirstRun) + { + return false; + } + Debug.Assert(outEdge.FixupType == FixupType.UnresolvedChildren); + if (!FindDependencies(outEdge, alreadyTraversed)) + { + return false; + } + } + return true; + } + + private void RemoveTokenByParent(NameFixupToken token) + { + object parentInstance = token.Target.Instance; + FrugalObjectList parentDependencies = _dependenciesByParentObject[parentInstance]; + Debug.Assert(parentDependencies.Contains(token)); + + if (parentDependencies.Count == 1) + { + _dependenciesByParentObject.Remove(parentInstance); + } + else + { + parentDependencies.Remove(token); + } + } + + private static void AddToMultiDict(Dictionary> dict, + TKey key, NameFixupToken value) + { + FrugalObjectList tokenList; + if (!dict.TryGetValue(key, out tokenList)) + { + tokenList = new FrugalObjectList(1); + dict.Add(key, tokenList); + } + tokenList.Add(value); + } + + private static void ThrowProvideValueCycle(IEnumerable markupExtensionTokens) + { + StringBuilder exceptionMessage = new StringBuilder(); + exceptionMessage.Append(SR.Get(SRID.ProvideValueCycle)); + foreach (NameFixupToken token in markupExtensionTokens) + { + exceptionMessage.AppendLine(); + string meName = token.ReferencedObject.ToString(); + if (token.LineNumber != 0) + { + if (token.LinePosition != 0) + { + exceptionMessage.Append(SR.Get(SRID.LineNumberAndPosition, meName, token.LineNumber, token.LinePosition)); + } + else + { + exceptionMessage.Append(SR.Get(SRID.LineNumberOnly, meName, token.LineNumber)); + } + } + else + { + exceptionMessage.Append(meName); + } + } + throw new XamlObjectWriterException(exceptionMessage.ToString()); + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/NameFixupToken.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/NameFixupToken.cs new file mode 100644 index 00000000000..4b1434ae293 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/NameFixupToken.cs @@ -0,0 +1,207 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using XAML3 = System.Windows.Markup; +using System.ComponentModel; +using System.Windows.Markup; +using System.Diagnostics; +using System.Xaml; +using MS.Internal.Xaml.Runtime; + +namespace MS.Internal.Xaml.Context +{ + internal enum FixupType + { + MarkupExtensionFirstRun, // An ME that can't be run because it has pending fixups on its properties + MarkupExtensionRerun, // An ME that was run and returned a FixupToken + PropertyValue, // A TC on a property that returned a FixupToken + ObjectInitializationValue, // A TC on an object that returned a FixupToken + UnresolvedChildren, // An object that can't be EndInited because it has pending fixups on its properties + }; + + internal class FixupTargetKeyHolder + { + public FixupTargetKeyHolder(Object key) + { + Key = key; + } + + public Object Key { get; set; } + } + + internal class FixupTarget : IAddLineInfo + { + /// + /// The Property the value will be assigned into. + /// In the case of FixupType.Property, this property will be set directly + /// when the Name is known. + /// + public XamlMember Property { get; set; } + + /// + /// The Instance the Property is on. + /// + public Object Instance { get; set; } + + /// + /// The x:Name, if any, of Instance. May not be set yet if InstanceIsOnTheStack is still true. + /// + public string InstanceName { get; set; } + + /// + /// The XamlType of the Instance (taken from the Frame, not exactly the type of the instance) + /// + public XamlType InstanceType { get; set; } + + /// + /// If Property is XamlLanguage.Items, then all the items being added to the target collection + /// are stored in a temporary holding collection. This is the index of the location in the collection + /// where this token is stored. + /// + public int TemporaryCollectionIndex { get; set; } + + /// + /// The LineNumber to use when calling EndInit on the Target Instance + /// + public int EndInstanceLineNumber { get; set; } + + /// + /// The LinePosition to use when calling EndInit on the Target Instance + /// + public int EndInstanceLinePosition { get; set; } + + /// + /// The ObjectWriterFrame and the FixupTarget need to both be updated when the Key is changed. + /// We create a KeyHolder to accomplish this + /// + public FixupTargetKeyHolder KeyHolder { get; set; } + + /// + /// Whether Instance is still on the live builder stack. We will use this to determine + /// whether to call EndInit on it when all fixups are resolved. + /// + public bool InstanceIsOnTheStack { get; set; } + + /// + /// Whether Instance was retrieved from a property (i.e. was a GO). If so, we don't call EndInit on it. + /// + public bool InstanceWasGotten { get; set; } + + XamlException IAddLineInfo.WithLineInfo(XamlException ex) + { + if (EndInstanceLineNumber > 0) + { + ex.SetLineInfo(EndInstanceLineNumber, EndInstanceLinePosition); + } + return ex; + } + } + + internal class NameFixupToken : IAddLineInfo + { + List _names; + List _nameScopeDictionaryList; + + public NameFixupToken() + { + _names = new List(); + _nameScopeDictionaryList = new List(); + Target = new FixupTarget(); + Target.TemporaryCollectionIndex = -1; + Target.InstanceIsOnTheStack = true; + } + + public bool CanAssignDirectly { get; set; } + public FixupType FixupType { get; set; } + + public int LineNumber { get; set; } + public int LinePosition { get; set; } + + public FixupTarget Target { get; set; } + + private XamlRuntime _runtime; + public XamlRuntime Runtime + { + get { return _runtime; } + set + { + Debug.Assert(_runtime == null); + _runtime = value; + } + } + + private ObjectWriterContext _targetContext; + public ObjectWriterContext TargetContext + { + get + { + if (_targetContext == null) + { + _targetContext = new ObjectWriterContext(SavedContext, null, null, Runtime); + } + return _targetContext; + } + } + + /// + /// Saved state for the reparse option. + /// + public XamlSavedContext SavedContext { get; set; } + + /// + /// Saved List of Name Scopes. With simple fixups we don't have a full context stack. + /// + public List NameScopeDictionaryList + { + get { return _nameScopeDictionaryList; } + } + + public List NeededNames + { + get { return _names; } + } + + // For simple fixups (CanAssignDirectly), this property is the referenced object when the + // name is finally resolved. + // For UnresolvedChildren fixups, this is the object that has + // unresolved children (which is in turn blocking its parent, Target.Instance, from being + // fully initialized). + // For other fixup types, this property is null. + public object ReferencedObject { get; set; } + + internal object ResolveName(string name) + { + object namedObject = null; + if (CanAssignDirectly) + { + foreach (INameScopeDictionary nameScope in NameScopeDictionaryList) + { + namedObject = nameScope.FindName(name); + if (namedObject != null) + { + break; + } + } + } + else + { + TargetContext.IsInitializedCallback = null; + bool isFullyInitialized; + namedObject = TargetContext.ResolveName(name, out isFullyInitialized); + } + return namedObject; + } + + XamlException IAddLineInfo.WithLineInfo(XamlException ex) + { + if (LineNumber > 0) + { + ex.SetLineInfo(LineNumber, LinePosition); + } + return ex; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ObjectWriterContext.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ObjectWriterContext.cs new file mode 100644 index 00000000000..85e52e385c3 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ObjectWriterContext.cs @@ -0,0 +1,1163 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Reflection; +using System.Security; +using XAML3 = System.Windows.Markup; +using System.Xaml; +using MS.Internal.Xaml.Runtime; +using System.Xaml.Schema; +using MS.Internal.Xaml.Parser; +using System.Xaml.MS.Impl; +using System.Xaml.Permissions; +using System.IO; +using System.Windows.Markup; +using System.Windows; + +namespace MS.Internal.Xaml.Context +{ + internal class ObjectWriterContext : XamlContext + { + private XamlContextStack _stack; + + private object _rootInstance = null; + + ServiceProviderContext _serviceProviderContext; + XamlRuntime _runtime; + int _savedDepth; // The depth of the "saved" part this context is based on. + bool _nameResolutionComplete; + XamlObjectWriterSettings _settings; + List _nameScopeInitializationCompleteSubscribers; + + public ObjectWriterContext(XamlSavedContext savedContext, + XamlObjectWriterSettings settings, INameScope rootNameScope, XamlRuntime runtime) + : base(savedContext.SchemaContext) + { + _stack = new XamlContextStack(savedContext.Stack, false); + if (settings != null) + { + _settings = settings.StripDelegates(); + } + _runtime = runtime; + BaseUri = savedContext.BaseUri; + // If the bottom of the stack is a (no XamlType) Value (reparse) then back-up onto it. + // Otherwise add a blank frame to isolate template use from the saved context. + switch(savedContext.SaveContextType) + { + case SavedContextType.Template: + // Templates always need a root namescope, to isolate them from the rest of the doc + INameScopeDictionary rootNameScopeDictionary = null; + if (rootNameScope == null) + { +#if TARGETTING35SP1 + rootNameScopeDictionary = new NameScopeDictionary(new NameScope()); +#else + rootNameScopeDictionary = new NameScope(); +#endif + } + else + { + rootNameScopeDictionary = rootNameScope as INameScopeDictionary; + + if (rootNameScopeDictionary == null) + { + rootNameScopeDictionary = new NameScopeDictionary(rootNameScope); + } + } + + // Push an extra frame to ensure that the template NameScope is + // not part of the saved context. Otherwise, the namescope + // will hold things alive as long as the template is alive + _stack.PushScope(); + _savedDepth = _stack.Depth; + _stack.CurrentFrame.NameScopeDictionary = rootNameScopeDictionary; + _stack.PushScope(); + break; + + case SavedContextType.ReparseValue: + case SavedContextType.ReparseMarkupExtension: + Debug.Assert(rootNameScope == null, "Cannot pass a new namescope in to a reparse context"); + _savedDepth = _stack.Depth - 1; + break; + } + } + + public ObjectWriterContext(XamlSchemaContext schemaContext, + XamlObjectWriterSettings settings, INameScope rootNameScope, XamlRuntime runtime) + : base(schemaContext) + { + _stack = new XamlContextStack(() => new ObjectWriterFrame()); + + INameScopeDictionary rootNameScopeDictionary = null; + if (rootNameScope == null) + { +#if TARGETTING35SP1 + rootNameScopeDictionary = new NameScopeDictionary(new NameScope()); +#else + rootNameScopeDictionary = new NameScope(); +#endif + } + else + { + rootNameScopeDictionary = rootNameScope as INameScopeDictionary; + + if (rootNameScopeDictionary == null) + { + rootNameScopeDictionary = new NameScopeDictionary(rootNameScope); + } + } + _stack.CurrentFrame.NameScopeDictionary = rootNameScopeDictionary; + _stack.PushScope(); // put a blank sentinal frame on the stack. + if (settings != null) + { + _settings = settings.StripDelegates(); + } + _runtime = runtime; + _savedDepth = 0; + } + + public override Assembly LocalAssembly + { + get + { + Assembly result = base.LocalAssembly; + if (result == null && _settings != null && _settings.AccessLevel != null) + { + result = Assembly.Load(_settings.AccessLevel.AssemblyAccessToAssemblyName); + base.LocalAssembly = result; + } + return result; + } + protected set { base.LocalAssembly = value; } + } + + internal ICheckIfInitialized IsInitializedCallback { get; set; } + + internal bool NameResolutionComplete + { + get { return _nameResolutionComplete; } + set + { + // Resolution should never become incomplete once it's complete + Debug.Assert(!_nameResolutionComplete || value); + _nameResolutionComplete = value; + } + } + + internal XamlRuntime Runtime + { + get + { + return _runtime; + } + } + + #region ServiceProvider Interfaces + + // This class doesn't implement the IServiceProvider. That is done + // with worker classes ValueConverterContext or MarkupConverterContext. + // The worker class implements IServiceProvider but uses the real + // context for the implementation of the actual services. + + internal Type ServiceProvider_Resolve(string qName) + { + // As soon as we have the necessary setting on ObjectWriter, we need to start passing + // the local assembly into the context; currently, this will only return publics. + XamlType xamlType = ServiceProvider_ResolveXamlType(qName); + if (xamlType == null || xamlType.UnderlyingType == null) + { + XamlTypeName name = XamlTypeName.Parse(qName, this._serviceProviderContext); + xamlType = this.GetXamlType(name, true, true); + throw new XamlParseException(SR.Get(SRID.TypeNotFound, xamlType.GetQualifiedName())); + } + return xamlType.UnderlyingType; + } + + internal XamlType ServiceProvider_ResolveXamlType(string qName) + { + return ResolveXamlType(qName, true); + } + + internal AmbientPropertyValue ServiceProvider_GetFirstAmbientValue(IEnumerable ceilingTypes, XamlMember[] properties) + { + List valueList = FindAmbientValues(ceilingTypes, /*searchLiveStackOnly*/false, /*types*/null, properties, true); + return (valueList.Count == 0) ? null : valueList[0]; + } + + internal object ServiceProvider_GetFirstAmbientValue(XamlType[] types) + { + List valueList = FindAmbientValues(types, true); + return (valueList.Count == 0) ? null : valueList[0]; + } + + internal IEnumerable ServiceProvider_GetAllAmbientValues(IEnumerable ceilingTypes, XamlMember[] properties) + { + List valueList = FindAmbientValues(ceilingTypes, /*searchLiveStackOnly*/false, /*types*/null, properties, /*stopAfterFirst*/ false); + return valueList; + } + + internal IEnumerable ServiceProvider_GetAllAmbientValues(XamlType[] types) + { + List valueList = FindAmbientValues(types, false); + return valueList; + } + + internal IEnumerable ServiceProvider_GetAllAmbientValues(IEnumerable ceilingTypes, bool searchLiveStackOnly, IEnumerable types, XamlMember[] properties) + { + List valueList = FindAmbientValues(ceilingTypes, searchLiveStackOnly, types, properties, false); + return valueList; + } + + private static void CheckAmbient(XamlMember xamlMember) + { + if (!xamlMember.IsAmbient) + { + throw new ArgumentException(SR.Get(SRID.NotAmbientProperty, xamlMember.DeclaringType.Name, xamlMember.Name), "xamlMember"); + } + } + + private static void CheckAmbient(XamlType xamlType) + { + if (!xamlType.IsAmbient) + { + throw new ArgumentException(SR.Get(SRID.NotAmbientType, xamlType.Name), "xamlType"); + } + } + + internal XamlObjectWriterSettings ServiceProvider_GetSettings() + { + if (_settings == null) + { + _settings = new XamlObjectWriterSettings(); + } + return _settings; + } + + #endregion + + // ----- abstracts overriden from XamlContext. + + public override void AddNamespacePrefix(String prefix, string xamlNS) + { + _stack.CurrentFrame.AddNamespace(prefix, xamlNS); + } + + public override string FindNamespaceByPrefix(string prefix) + { + string xamlNs; + ObjectWriterFrame frame = _stack.CurrentFrame; + + while (frame.Depth > 0) + { + if (frame.TryGetNamespaceByPrefix(prefix, out xamlNs)) + { + return xamlNs; + } + frame = (ObjectWriterFrame)frame.Previous; + } + return null; + } + + public override IEnumerable GetNamespacePrefixes() + { + ObjectWriterFrame frame = _stack.CurrentFrame; + Dictionary keys = new Dictionary(); + + while (frame.Depth > 0) + { + if (frame._namespaces != null) + { + foreach (NamespaceDeclaration namespaceDeclaration in frame.GetNamespacePrefixes()) + { + if (!keys.ContainsKey(namespaceDeclaration.Prefix)) + { + keys.Add(namespaceDeclaration.Prefix, null); + yield return namespaceDeclaration; + } + } + } + frame = (ObjectWriterFrame)frame.Previous; + } + } + + // Method to easily add the lineinfo to a Xaml Exception. + public XamlException WithLineInfo(XamlException ex) + { + ex.SetLineInfo(LineNumber, LinePosition); + return ex; + } + + // ----- methods to support the Service Providers + + internal ServiceProviderContext ServiceProviderContext + { + get + { + if (null == _serviceProviderContext) + { + _serviceProviderContext = new ServiceProviderContext(this); + } + return _serviceProviderContext; + } + } + + internal XamlType GetDestinationType() + { + ObjectWriterFrame frame = _stack.CurrentFrame; + + if (frame == null) + { + return null; + } + + if (frame.Instance != null && frame.XamlType == null) + { + // + // Text/TypeConverter, we need to go up a frame + frame = frame.Previous as ObjectWriterFrame; + } + + if (frame.Member == XamlLanguage.Initialization) + { + return frame.XamlType; + } + return frame.Member.Type; + } + + private List FindAmbientValues(IEnumerable ceilingTypesEnumerable, + bool searchLiveStackOnly, + IEnumerable types, + XamlMember[] properties, + bool stopAfterFirst) + { + ArrayHelper.ForAll(properties, CheckAmbient); + List ceilingTypes = ArrayHelper.ToList(ceilingTypesEnumerable); + + List retList = new List(); + + // Start the search for ambient properties and types starting with the parent frame. + ObjectWriterFrame frame = _stack.PreviousFrame; + ObjectWriterFrame lowerFrame = _stack.CurrentFrame; + + while (frame.Depth >= 1) + { + if (searchLiveStackOnly && frame.Depth <= SavedDepth) + { + break; + } + + object inst = frame.Instance; + + if (types != null) + { + foreach (XamlType type in types) + { + if (frame.XamlType != null && frame.XamlType.CanAssignTo(type)) + { + if (inst != null) + { + AmbientPropertyValue apValue = new AmbientPropertyValue(null, inst); + retList.Add(apValue); + } + } + } + } + + if (properties != null) + { + foreach (XamlMember prop in properties) + { + bool returnAmbientValue = false; + object value = null; + + if (frame.XamlType != null && frame.XamlType.CanAssignTo(prop.DeclaringType)) + { + if (inst != null) + { + // If we are searching from inside the target Ambient property, + // (like StaticResource inside a ResourceDictionary) + // and the object is bottom-up, then it won't be assigned to + // the object but will only exist on the parse stack. + // If it is top-down it will be attached to the instance already + // and the normal path will serve. + if (prop == frame.Member && lowerFrame.Instance != null + && lowerFrame.XamlType != null && !lowerFrame.XamlType.IsUsableDuringInitialization) + { + // One last thing to check: If the object we are inside is a ME + // then we are inside a call to ProvideValue and we don't want to + // return a reference to ourselves to ourselves. + if (!typeof(MarkupExtension).IsAssignableFrom(lowerFrame.Instance.GetType())) + { + returnAmbientValue = true; + value = lowerFrame.Instance; + } + } + else + { // The Ambient Property is either Fully build or not set. + + // FIRST: Ask the object (via IQueryAmbient interface) if it has a value for this property. + // This is usefull to prevent needless creation of empty lazy properties. + var ambientCtrl = inst as IQueryAmbient; + + // If there is no ambientControl or if ambientControl says YES, then get the property value. + if (ambientCtrl == null || ambientCtrl.IsAmbientPropertyAvailable(prop.Name)) + { + // Demand for XamlLoadPermission will fail if we're trying to + // access an internal property from a partial-trust ME/TC + returnAmbientValue = true; + value = _runtime.GetValue(inst, prop); + } + } + } + + if (returnAmbientValue) + { + AmbientPropertyValue apValue = new AmbientPropertyValue(prop, value); + retList.Add(apValue); + } + } + } + } + + if (stopAfterFirst && retList.Count > 0) + { + break; + } + + if (ceilingTypes != null) + { + if (ceilingTypes.Contains(frame.XamlType)) + { + break; + } + } + + lowerFrame = frame; + frame = (ObjectWriterFrame)frame.Previous; + Debug.Assert(frame != null); + } + + return retList; + } + + private List FindAmbientValues(XamlType[] types, bool stopAfterFirst) + { + ArrayHelper.ForAll(types, CheckAmbient); + + List retList = new List(); + + // Start the search for ambient properties with the parent frame. + ObjectWriterFrame frame = _stack.PreviousFrame; + ObjectWriterFrame lowerFrame = _stack.CurrentFrame; + + while (frame.Depth >= 1) + { + foreach (XamlType type in types) + { + object inst = frame.Instance; + + if (frame.XamlType != null && frame.XamlType.CanAssignTo(type)) + { + if (inst != null) + { + retList.Add(inst); + if (stopAfterFirst) + { + return retList; + } + } + } + } + + lowerFrame = frame; + frame = (ObjectWriterFrame)frame.Previous; + Debug.Assert(frame != null); + } + + return retList; + } + + // ----- new public methods. + + public void PushScope() + { + _stack.PushScope(); + } + + // Don't call this - serious workaround + public void LiftScope() + { + _stack.Depth--; + } + + // Don't call this - serious workaround + public void UnLiftScope() + { + _stack.Depth++; + } + + public void PopScope() + { + _stack.PopScope(); + } + + /// + /// Total depth of the stack SavedDepth+LiveDepth + /// + public int Depth + { + get { return _stack.Depth; } + } + + /// + /// The Depth of the Saved (template) part. + /// + public int SavedDepth + { + get { return _savedDepth; } + } + + /// + /// The Depth of the Stack above the Saved (template) part + /// + public int LiveDepth + { + get { return Depth - SavedDepth; } + } + + public XamlType CurrentType + { + get { return _stack.CurrentFrame.XamlType; } + set { _stack.CurrentFrame.XamlType = value; } + } + + public XamlType ParentType + { + get { return _stack.PreviousFrame.XamlType; } + } + + public XamlType GrandParentType + { + get { return (_stack.PreviousPreviousFrame != null) ? _stack.PreviousPreviousFrame.XamlType : null; } + } + + public XamlMember CurrentProperty + { + get { return _stack.CurrentFrame.Member; } + set { _stack.CurrentFrame.Member = value; } + } + + public XamlMember ParentProperty + { + get { return _stack.PreviousFrame.Member; } + } + + public XamlMember GrandParentProperty + { + get { return _stack.PreviousPreviousFrame.Member; } + } + + public Object CurrentInstance + { + get { return _stack.CurrentFrame.Instance; } + set { _stack.CurrentFrame.Instance = value; } + } + + public Object ParentInstance + { + get { return _stack.PreviousFrame.Instance; } + } + + public Object GrandParentInstance + { + get { return (_stack.PreviousPreviousFrame != null) ? _stack.PreviousPreviousFrame.Instance : null; } + } + + public Object CurrentCollection + { + get { return _stack.CurrentFrame.Collection; } + set { _stack.CurrentFrame.Collection = value; } + } + + public object ParentCollection + { + get { return _stack.PreviousFrame.Collection; } + } + + public bool CurrentWasAssignedAtCreation + { + get { return _stack.CurrentFrame.WasAssignedAtCreation; } + set { _stack.CurrentFrame.WasAssignedAtCreation = value; } + } + + public bool CurrentIsObjectFromMember + { + get { return _stack.CurrentFrame.IsObjectFromMember; } + set { _stack.CurrentFrame.IsObjectFromMember = value; } + } + + public bool ParentIsObjectFromMember + { + get { return _stack.PreviousFrame.IsObjectFromMember; } + } + + public bool GrandParentIsObjectFromMember + { + get { return (_stack.PreviousPreviousFrame != null) ? _stack.PreviousPreviousFrame.IsObjectFromMember : false; } + } + + public bool CurrentIsPropertyValueSet + { + // get { return _stack.CurrentFrame.IsPropertyValueSet; } Currently Unused (FxCop) + set { _stack.CurrentFrame.IsPropertyValueSet = value; } + } + + public bool ParentIsPropertyValueSet + { + get { return _stack.PreviousFrame.IsPropertyValueSet; } + set { _stack.PreviousFrame.IsPropertyValueSet = value; } + } + + public bool CurrentIsTypeConvertedObject + { + get { return _stack.CurrentFrame.IsTypeConvertedObject; } + set { _stack.CurrentFrame.IsTypeConvertedObject = value; } + } + + public Dictionary CurrentPreconstructionPropertyValues + { + get { return _stack.CurrentFrame.PreconstructionPropertyValues; } + } + + public bool CurrentHasPreconstructionPropertyValuesDictionary + { + get { return _stack.CurrentFrame.HasPreconstructionPropertyValuesDictionary; } + } + + public Dictionary ParentPreconstructionPropertyValues + { + get { return _stack.PreviousFrame.PreconstructionPropertyValues; } + } + + public HashSet CurrentAssignedProperties + { + get { return _stack.CurrentFrame.AssignedProperties; } + } + + public HashSet ParentAssignedProperties + { + get { return _stack.PreviousFrame.AssignedProperties; } + } + + public string CurrentInstanceRegisteredName + { + get { return _stack.CurrentFrame.InstanceRegisteredName; } + set { _stack.CurrentFrame.InstanceRegisteredName = value; } + } + + public string ParentInstanceRegisteredName + { + get { return _stack.PreviousFrame.InstanceRegisteredName; } + set { _stack.PreviousFrame.InstanceRegisteredName = value; } + } + + public Uri BaseUri { get; set; } + + public int LineNumber { get; set; } + public int LinePosition { get; set; } + + // Used only for BeginInitHandler, in place of BaseUri. + public Uri SourceBamlUri + { + get { return _settings != null ? _settings.SourceBamlUri : null; } + } + + // This specifically stores the start line number for a start object for consistency + public int LineNumber_StartObject { get; set; } + + // This specifically stores the start line position for a start object for consistency + public int LinePosition_StartObject { get; set; } + + public INameScopeDictionary CurrentNameScope + { + get + { + return LookupNameScopeDictionary((ObjectWriterFrame)_stack.CurrentFrame); + } + } + + public INameScopeDictionary ParentNameScope + { + get + { + return LookupNameScopeDictionary((ObjectWriterFrame)_stack.PreviousFrame); + } + } + + public INameScopeDictionary GrandParentNameScope + { + get + { + return LookupNameScopeDictionary((ObjectWriterFrame)_stack.PreviousPreviousFrame); + } + } + + public INameScopeDictionary RootNameScope + { + get + { + ObjectWriterFrame rootFrame = _stack.GetFrame(SavedDepth + 1); + return LookupNameScopeDictionary(rootFrame); + } + } + + /// + /// From x:Arguments or ME positional syntax. + /// + public object[] CurrentCtorArgs + { + get { return _stack.CurrentFrame.PositionalCtorArgs; } + set { _stack.CurrentFrame.PositionalCtorArgs = value; } + } + + public object CurrentKey + { + get { return _stack.CurrentFrame.Key; } + } + + public bool CurrentIsKeySet + { + get { return _stack.CurrentFrame.IsKeySet; } + } + + public object ParentKey + { + get { return _stack.PreviousFrame.Key; } + set + { + _stack.PreviousFrame.Key = value; + } + } + + public bool CurrentKeyIsUnconverted + { + get { return _stack.CurrentFrame.KeyIsUnconverted; } + set { _stack.CurrentFrame.KeyIsUnconverted = value; } + } + + public bool ParentKeyIsUnconverted + { + // Write-only property: Getter was dead code, so removed per FxCop; add back if needed. + set { _stack.PreviousFrame.KeyIsUnconverted = value; } + } + + public bool ParentShouldConvertChildKeys + { + get { return _stack.PreviousFrame.ShouldConvertChildKeys; } + set { _stack.PreviousPreviousFrame.ShouldConvertChildKeys = value; } + } + + public bool GrandParentShouldConvertChildKeys + { + get { return _stack.PreviousPreviousFrame.ShouldConvertChildKeys; } + set { _stack.PreviousPreviousFrame.ShouldConvertChildKeys = value; } + } + + public bool ParentShouldNotConvertChildKeys + { + get { return _stack.PreviousFrame.ShouldNotConvertChildKeys; } + set { _stack.PreviousPreviousFrame.ShouldNotConvertChildKeys = value; } + } + + public bool GrandParentShouldNotConvertChildKeys + { + get { return _stack.PreviousPreviousFrame.ShouldNotConvertChildKeys; } + } + + public object RootInstance + { + get + { + //evaluate if _rootInstance should just always look at _rootFrame.Instance instead of caching an instance + if (_rootInstance == null) + { + ObjectWriterFrame rootFrame = GetTopFrame(); + _rootInstance = rootFrame.Instance; + } + return _rootInstance; + } + } + + // Consider replacing GetTopFrame with _rootFrame, _liveRootFrame + private ObjectWriterFrame GetTopFrame() + { + if (_stack.Depth == 0) + { + return null; + } + + XamlFrame frame = _stack.CurrentFrame; + while (frame.Depth > 1) + { + frame = frame.Previous; + } + return (ObjectWriterFrame)frame; + } + + private INameScopeDictionary LookupNameScopeDictionary(ObjectWriterFrame frame) + { + if (frame.NameScopeDictionary == null) + { + if (frame.XamlType != null && frame.XamlType.IsNameScope) + { + frame.NameScopeDictionary = frame.Instance as INameScopeDictionary ?? new NameScopeDictionary(frame.Instance as INameScope); + } + if (frame.NameScopeDictionary == null) + { + if (frame.Depth == 1) + { + frame.NameScopeDictionary = HuntAroundForARootNameScope(frame); + } + else if (frame.Depth > 1) + { + if (frame.Depth == SavedDepth + 1 && + _settings != null && !_settings.RegisterNamesOnExternalNamescope) + { +#if TARGETTING35SP1 + frame.NameScopeDictionary = new NameScopeDictionary(new NameScope()); +#else + frame.NameScopeDictionary = new NameScope(); +#endif + } + else + { + var parentFrame = (ObjectWriterFrame)frame.Previous; + frame.NameScopeDictionary = LookupNameScopeDictionary(parentFrame); + } + } + } + } + // We are sure to find a name scope at the root (at least). + Debug.Assert(frame.NameScopeDictionary != null || frame.Depth == 0); + return frame.NameScopeDictionary; + } + + public IEnumerable StackWalkOfNameScopes + { + get + { + var frame = (ObjectWriterFrame)_stack.CurrentFrame; + INameScopeDictionary previousNameScopeDictionary = null; + INameScopeDictionary nameScopeDictionary = null; + while (frame.Depth > 0) + { + nameScopeDictionary = LookupNameScopeDictionary(frame); + Debug.Assert(nameScopeDictionary != null); + if (frame.NameScopeDictionary != previousNameScopeDictionary) + { + previousNameScopeDictionary = nameScopeDictionary; + yield return nameScopeDictionary; + } + frame = (ObjectWriterFrame)frame.Previous; + } + // return the provided root namescope if it's different from the document root namescope + if (frame.NameScopeDictionary != null && frame.NameScopeDictionary != previousNameScopeDictionary) + { + yield return frame.NameScopeDictionary; + } + } + } + + public bool IsOnTheLiveStack(object instance) + { + var frame = (ObjectWriterFrame)_stack.CurrentFrame; + while (frame.Depth > SavedDepth) + { + if (instance == frame.Instance) + { + return true; + } + frame = (ObjectWriterFrame)frame.Previous; + } + return false; + } + + private INameScopeDictionary HuntAroundForARootNameScope(ObjectWriterFrame rootFrame) + { + Debug.Assert(rootFrame.Depth == 1); + + object inst = rootFrame.Instance; + if (inst == null && rootFrame.XamlType.IsNameScope) + { + throw new InvalidOperationException(SR.Get(SRID.NameScopeOnRootInstance)); + } + + INameScopeDictionary nameScopeDictionary = null; + + nameScopeDictionary = inst as INameScopeDictionary; + + if (nameScopeDictionary == null) + { + INameScope nameScope = inst as INameScope; + if (nameScope != null) + { + nameScopeDictionary = new NameScopeDictionary(nameScope); + } + } + + // If the root instance isn't a name scope + // then perhaps it designated a property as the name scope. + if (nameScopeDictionary == null) + { + XamlType xamlType = rootFrame.XamlType; + if (xamlType.UnderlyingType != null) + { + // Get the Name Scope Property (from attribute on the class) + XamlMember nameScopeProperty = TypeReflector.LookupNameScopeProperty(xamlType); + if (nameScopeProperty != null) + { + // Read the value of the property. If it is an object we are good. + // if it is null create a stock name scope dictionary object and assign it back. + INameScope nameScope = (INameScope)_runtime.GetValue(inst, nameScopeProperty, false); + if (nameScope == null) + { +#if TARGETTING35SP1 + nameScopeDictionary = new NameScopeDictionary(new NameScope()); +#else + nameScopeDictionary = new NameScope(); +#endif + _runtime.SetValue(inst, nameScopeProperty, nameScopeDictionary); + } + else + { + nameScopeDictionary = nameScope as INameScopeDictionary; + if (nameScopeDictionary == null) + { + nameScopeDictionary = new NameScopeDictionary(nameScope); + } + } + } + } + } + + if (nameScopeDictionary == null && _settings != null + && _settings.RegisterNamesOnExternalNamescope) + { + ObjectWriterFrame frameZero = (ObjectWriterFrame)rootFrame.Previous; + nameScopeDictionary = frameZero.NameScopeDictionary; + } + + // Otherwise we still need a namescope at the root of the parse + // for our own usage. For IXamlNameResolver() to use. + if (nameScopeDictionary == null) + { +#if TARGETTING35SP1 + nameScopeDictionary = new NameScopeDictionary(new NameScope()); +#else + nameScopeDictionary = new NameScope(); +#endif + } + + rootFrame.NameScopeDictionary = nameScopeDictionary; + return nameScopeDictionary; + } + + public XamlSavedContext GetSavedContext(SavedContextType savedContextType) + { + // Ensure that we have a root namescope before cloning the stack + ObjectWriterFrame topFrame = GetTopFrame(); + if (topFrame.NameScopeDictionary == null) + { + topFrame.NameScopeDictionary = LookupNameScopeDictionary(topFrame); + } + + // Clone the stack + var newStack = new XamlContextStack(_stack, true); + XamlSavedContext savedContext = new XamlSavedContext(savedContextType, this, newStack); + return savedContext; + } + + public object ResolveName(string name, out bool isFullyInitialized) + { + isFullyInitialized = false; + object value = null; + foreach (INameScope nameScope in StackWalkOfNameScopes) + { + object obj = nameScope.FindName(name); + if (obj != null) + { + if (IsInitializedCallback != null) + { + isFullyInitialized = IsInitializedCallback.IsFullyInitialized(obj); + } + if (NameResolutionComplete || isFullyInitialized || IsInitializedCallback == null) + { + value = obj; + } + break; + } + } + return value; + } + + public IEnumerable> GetAllNamesAndValuesInScope() + { + List> allNamesAndValues = new List>(); + // + // This could be optimized further by enumerating the collection of namescopes, getting the NamesAndValues + // from each, calculating the total size required, pre-allocating the final collection, and then + // inserting the names and values from each name scope into it. + // However unless we have a lot of namescopes in the graph, which doesn't seem likely, this seems like overkill + foreach (INameScopeDictionary nameScopeDictionary in StackWalkOfNameScopes) + { + foreach (KeyValuePair nameValuePair in nameScopeDictionary) + { + if (allNamesAndValues.Exists(pair => pair.Key == nameValuePair.Key)) + { + continue; + } + allNamesAndValues.Add(nameValuePair); + } + } + return allNamesAndValues; + } + + internal void AddNameScopeInitializationCompleteSubscriber(EventHandler handler) + { + if (_nameScopeInitializationCompleteSubscribers == null) + { + _nameScopeInitializationCompleteSubscribers = new List(); + } + + var subscriber = new NameScopeInitializationCompleteSubscriber { Handler = handler }; + subscriber.NameScopeDictionaryList.AddRange(StackWalkOfNameScopes); + + _nameScopeInitializationCompleteSubscribers.Add(subscriber); + } + + internal void RemoveNameScopeInitializationCompleteSubscriber(EventHandler handler) + { + var subscriber = _nameScopeInitializationCompleteSubscribers.Find(o => o.Handler == handler); + if (subscriber != null) + { + _nameScopeInitializationCompleteSubscribers.Remove(subscriber); + } + } + + internal void RaiseNameScopeInitializationCompleteEvent() + { + if (_nameScopeInitializationCompleteSubscribers != null) + { + EventArgs e = new EventArgs(); + foreach (var subscriber in _nameScopeInitializationCompleteSubscribers) + { + var resolver = new StackWalkNameResolver(subscriber.NameScopeDictionaryList); + subscriber.Handler(resolver, e); + } + } + } + + internal class NameScopeInitializationCompleteSubscriber + { + List _nameScopeDictionaryList = new List(); + + public EventHandler Handler + { + get; set; + } + + public List NameScopeDictionaryList + { + get { return _nameScopeDictionaryList; } + } + } + + private class StackWalkNameResolver : IXamlNameResolver + { + List _nameScopeDictionaryList; + + public StackWalkNameResolver(List nameScopeDictionaryList) + { + _nameScopeDictionaryList = nameScopeDictionaryList; + } + + public bool IsFixupTokenAvailable + { + get + { + return false; + } + } + + public object GetFixupToken(IEnumerable name) + { + return null; + } + + public object GetFixupToken(IEnumerable name, bool canAssignDirectly) + { + return null; + } + + public event EventHandler OnNameScopeInitializationComplete + { + // at this point all name scopes have been completed, and we will + // not raise any event for subscriptions that come after this. + add + { + } + + remove + { + } + } + + public object Resolve(string name) + { + object value = null; + foreach (INameScopeDictionary nameScope in _nameScopeDictionaryList) + { + object obj = nameScope.FindName(name); + if (obj != null) + { + value = obj; + break; + } + } + return value; + } + + public object Resolve(string name, out bool isFullyInitialized) + { + // This resolver is only used after the parse is complete, including completing + // name references. So all objects are fully initialized. + object result = Resolve(name); + isFullyInitialized = (result != null); + return result; + } + + public IEnumerable> GetAllNamesAndValuesInScope() + { + List> allNamesAndValues = new List>(); + + foreach (INameScopeDictionary nameScopeDictionary in _nameScopeDictionaryList) + { + foreach (KeyValuePair nameValuePair in nameScopeDictionary) + { + if (allNamesAndValues.Exists(pair => pair.Key == nameValuePair.Key)) + { + continue; + } + allNamesAndValues.Add(nameValuePair); + } + } + return allNamesAndValues; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ObjectWriterFrame.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ObjectWriterFrame.cs new file mode 100644 index 00000000000..877d19ba6ae --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ObjectWriterFrame.cs @@ -0,0 +1,232 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using XAML3 = System.Windows.Markup; +using System.Xaml; +using System.Xaml.MS.Impl; +using System.Windows.Markup; + +namespace MS.Internal.Xaml.Context +{ + [DebuggerDisplay("{ToString()}")] + internal class ObjectWriterFrame : XamlCommonFrame + { + private ObjectWriterFrameFlags _flags; + private Dictionary _preconstructionPropertyValues; + private HashSet _assignedProperties; + private Object _key; + + public ObjectWriterFrame() + : base() + { } + + + public ObjectWriterFrame(ObjectWriterFrame source) + : base(source) + { + // Calling the getter will instantiate new Dictionaries. + // So we just check the field instead to verify that it isn't + // being used. + if (source._preconstructionPropertyValues != null) + { + _preconstructionPropertyValues = new Dictionary(source.PreconstructionPropertyValues); + } + if (source._assignedProperties != null) + { + _assignedProperties = new HashSet(source.AssignedProperties); + } + _key = source._key; + _flags = source._flags; + Instance = source.Instance; + Collection = source.Collection; + NameScopeDictionary = source.NameScopeDictionary; + PositionalCtorArgs = source.PositionalCtorArgs; + InstanceRegisteredName = source.InstanceRegisteredName; + } + + public override void Reset() + { + base.Reset(); + _preconstructionPropertyValues = null; + _assignedProperties = null; + Instance = null; + Collection = null; + NameScopeDictionary = null; + PositionalCtorArgs = null; + InstanceRegisteredName = null; + _flags = ObjectWriterFrameFlags.None; + _key = null; + } + + // Must be able to clone the ObjectWriterFrame as + // context for Templates + public override XamlFrame Clone() + { + return new ObjectWriterFrame(this); + } + + public override string ToString() + { + string type = (this.XamlType == null) ? String.Empty : this.XamlType.Name; + string prop = (this.Member == null) ? "-" : this.Member.Name; + string inst = (Instance == null) ? "-" : ((Instance is String) ? Instance.ToString() : "*"); + string coll = (Collection == null) ? "-" : "*"; + string res = KS.Fmt("{0}.{1} inst={2} coll={3}", + type, prop, inst, coll); + return res; + } + + public Object Instance { get; set; } + public Object Collection { get; set; } + + public bool WasAssignedAtCreation + { + get { return GetFlag(ObjectWriterFrameFlags.WasAssignedAtCreation); } + set { SetFlag(ObjectWriterFrameFlags.WasAssignedAtCreation, value); } + } + + public bool IsObjectFromMember + { + get { return GetFlag(ObjectWriterFrameFlags.IsObjectFromMember); } + set { SetFlag(ObjectWriterFrameFlags.IsObjectFromMember, value); } + } + + public bool IsPropertyValueSet + { + get { return GetFlag(ObjectWriterFrameFlags.IsPropertyValueSet); } + set { SetFlag(ObjectWriterFrameFlags.IsPropertyValueSet, value); } + } + + public bool IsKeySet + { + get { return GetFlag(ObjectWriterFrameFlags.IsKeySet); } + private set { SetFlag(ObjectWriterFrameFlags.IsKeySet, value); } + } + + public bool IsTypeConvertedObject + { + get { return GetFlag(ObjectWriterFrameFlags.IsTypeConvertedObject); } + set { SetFlag(ObjectWriterFrameFlags.IsTypeConvertedObject, value); } + } + + // The following three flags are interrelated. See XamlObjectWritr.Logic_ShouldConvertKey + // for more details. + public bool KeyIsUnconverted + { + get { return GetFlag(ObjectWriterFrameFlags.KeyIsUnconverted); } + set { SetFlag(ObjectWriterFrameFlags.KeyIsUnconverted, value); } + } + + public bool ShouldConvertChildKeys + { + get { return GetFlag(ObjectWriterFrameFlags.ShouldConvertChildKeys); } + set { SetFlag(ObjectWriterFrameFlags.ShouldConvertChildKeys, value); } + } + + public bool ShouldNotConvertChildKeys + { + get { return GetFlag(ObjectWriterFrameFlags.ShouldNotConvertChildKeys); } + set { SetFlag(ObjectWriterFrameFlags.ShouldNotConvertChildKeys, value); } + } + + public INameScopeDictionary NameScopeDictionary { get; set; } + public object[] PositionalCtorArgs { get; set; } + public object Key + { + get + { + // We use a special KeyHolder in some x:Reference scenarios. + // We need to unwrap this when returning. + FixupTargetKeyHolder ftkh = _key as FixupTargetKeyHolder; + if (ftkh != null) + { + return ftkh.Key; + } + return _key; + } + set + { + _key = value; + IsKeySet = true; + } + } + + /// + /// The x:Name of this.Instance. + /// Used to trigger forward ref resolution. + /// + public string InstanceRegisteredName { get; set; } + + /// + /// Collection of directives set on this object, because + /// directives can't be stored on the object. + /// + public Dictionary PreconstructionPropertyValues + { + get + { + if (_preconstructionPropertyValues == null) + { + _preconstructionPropertyValues = new Dictionary(); + } + return _preconstructionPropertyValues; + } + } + + public bool HasPreconstructionPropertyValuesDictionary + { + get { return _preconstructionPropertyValues != null; } + } + + /// + /// All Properties that are set so far. + /// + public HashSet AssignedProperties + { + get + { + if (_assignedProperties == null) + { + _assignedProperties = new HashSet(); + } + return _assignedProperties; + } + } + + private bool GetFlag(ObjectWriterFrameFlags flag) + { + return (_flags & flag) != ObjectWriterFrameFlags.None; + } + + private void SetFlag(ObjectWriterFrameFlags flag, bool value) + { + if (value) + { + _flags = _flags | flag; + } + else + { + _flags = _flags & ~flag; + } + } + + [Flags] + private enum ObjectWriterFrameFlags : byte + { + None = 0, + WasAssignedAtCreation = 0x01, + IsObjectFromMember = 0x02, + IsPropertyValueSet = 0x04, + IsKeySet = 0x08, + IsTypeConvertedObject = 0x10, + KeyIsUnconverted = 0x20, + ShouldConvertChildKeys = 0x40, + ShouldNotConvertChildKeys = 0x80 + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/SavedContext.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/SavedContext.cs new file mode 100644 index 00000000000..ad310a06ae6 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/SavedContext.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using MS.Internal.Xaml.Context; +using System.Windows.Markup; + +namespace System.Xaml +{ + internal enum SavedContextType { Template, ReparseValue, ReparseMarkupExtension } + + internal class XamlSavedContext + { + private XamlSchemaContext _context; + private XamlContextStack _stack; + private SavedContextType _savedContextType; + + public XamlSavedContext(SavedContextType savedContextType, ObjectWriterContext owContext, XamlContextStack stack) + { + //We should harvest all information necessary from the xamlContext so that we can answer all ServiceProvider based questions. + _savedContextType = savedContextType; + _context = owContext.SchemaContext; + _stack = stack; + + // Null out CurrentFrameValue in case of template to save on survived allocations + if (savedContextType == SavedContextType.Template) + { + stack.CurrentFrame.Instance = null; + } + this.BaseUri = owContext.BaseUri; + } + + public SavedContextType SaveContextType { get { return _savedContextType; } } + public XamlContextStack Stack { get { return _stack; } } + public XamlSchemaContext SchemaContext { get { return _context; } } + public Uri BaseUri { get; private set; } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ServiceProviderContext.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ServiceProviderContext.cs new file mode 100644 index 00000000000..3266139d8ff --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/ServiceProviderContext.cs @@ -0,0 +1,429 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Windows.Markup; +using System.Xaml; +using MS.Internal.Xaml.Context; + +namespace MS.Internal.Xaml +{ +internal class ServiceProviderContext : ITypeDescriptorContext, // derives from IServiceProvider + IServiceProvider, + IXamlTypeResolver, + IUriContext, + IAmbientProvider, + IXamlSchemaContextProvider, + IRootObjectProvider, + IXamlNamespaceResolver, + IProvideValueTarget, + IXamlNameResolver, + IDestinationTypeProvider, + IXamlLineInfo + { + ObjectWriterContext _xamlContext; + + public ServiceProviderContext(ObjectWriterContext context) + { + _xamlContext = context; + } + + #region XamlServiceProviderContext Methods + object IServiceProvider.GetService(Type serviceType) + { + if (serviceType == typeof(IXamlTypeResolver)) + { + return this; + } + else if (serviceType == typeof(IUriContext)) + { + return this; + } + else if (serviceType == typeof(IAmbientProvider)) + { + return this; + } + else if (serviceType == typeof(IXamlSchemaContextProvider)) + { + return this; + } + else if (serviceType == typeof(IProvideValueTarget)) + { + return this; + } + else if (serviceType == typeof(IRootObjectProvider)) + { + return this; + } + else if (serviceType == typeof(IXamlNamespaceResolver)) + { + return this; + } + else if (serviceType == typeof(IXamlNameResolver)) + { + return this; + } + else if (serviceType == typeof(IXamlObjectWriterFactory)) + { + return new XamlObjectWriterFactory(_xamlContext); + } + else if (serviceType == typeof(IDestinationTypeProvider)) + { + return this; + } + else if (serviceType == typeof(IXamlLineInfo)) + { + return this; + } + + return null; + } + #endregion + + #region ITypeDescriptorContext Methods + // ITypeDescriptorContext derives from IServiceProvider. + void ITypeDescriptorContext.OnComponentChanged() + { + } + + bool ITypeDescriptorContext.OnComponentChanging() + { + return false; + } + + IContainer ITypeDescriptorContext.Container + { + get { return null; } + } + + object ITypeDescriptorContext.Instance + { + get { return null; } + } + + PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor + { + get { return null; } + } + #endregion + + #region IXamlTypeResolver Members + Type IXamlTypeResolver.Resolve(string qName) + { + return _xamlContext.ServiceProvider_Resolve(qName); + } + #endregion + + #region IUriContext Members + Uri IUriContext.BaseUri + { + get { return _xamlContext.BaseUri; } + set { throw new InvalidOperationException(SR.Get(SRID.MustNotCallSetter)); } + } + #endregion + + #region IAmbientProvider Members + AmbientPropertyValue IAmbientProvider.GetFirstAmbientValue( + IEnumerable ceilingTypes, + params XamlMember[] properties) + { + if (properties == null) + { + throw new ArgumentNullException("properties"); + } + + foreach (var property in properties) + { + if (property == null) + { + // we don't allow any property to be null + throw new ArgumentException(SR.Get(SRID.ValueInArrayIsNull, "properties"));; + } + } + + return _xamlContext.ServiceProvider_GetFirstAmbientValue(ceilingTypes, properties); + } + + object IAmbientProvider.GetFirstAmbientValue(params XamlType[] types) + { + if (types == null) + { + throw new ArgumentNullException("types"); + } + + foreach (var type in types) + { + if (type == null) + { + // we don't allow any type to be null + throw new ArgumentException(SR.Get(SRID.ValueInArrayIsNull, "types")); + } + } + return _xamlContext.ServiceProvider_GetFirstAmbientValue(types); + } + + + IEnumerable IAmbientProvider.GetAllAmbientValues( + IEnumerable ceilingTypes, + params XamlMember[] properties) + { + if (properties == null) + { + throw new ArgumentNullException("properties"); + } + + foreach (var property in properties) + { + if (property == null) + { + // we don't allow any property to be null + throw new ArgumentException(SR.Get(SRID.ValueInArrayIsNull, "properties")); + } + } + + return _xamlContext.ServiceProvider_GetAllAmbientValues(ceilingTypes, properties); + } + + IEnumerable IAmbientProvider.GetAllAmbientValues(params XamlType[] types) + { + if (types == null) + { + throw new ArgumentNullException("types"); + } + + foreach (var type in types) + { + if (type == null) + { + // we don't allow any type to be null + throw new ArgumentException(SR.Get(SRID.ValueInArrayIsNull, "types")); + } + } + + return _xamlContext.ServiceProvider_GetAllAmbientValues(types); + } + + IEnumerable IAmbientProvider.GetAllAmbientValues( + IEnumerable ceilingTypes, + bool searchLiveStackOnly, + IEnumerable types, + params XamlMember[] properties) + { + if (properties == null) + { + throw new ArgumentNullException("properties"); + } + + foreach (var property in properties) + { + if (property == null) + { + // we don't allow any property to be null + throw new ArgumentException(SR.Get(SRID.ValueInArrayIsNull, "properties")); + } + } + + return _xamlContext.ServiceProvider_GetAllAmbientValues(ceilingTypes, searchLiveStackOnly, types, properties); + } + + #endregion + + #region IXamlSchemaContextProvider Members + XamlSchemaContext IXamlSchemaContextProvider.SchemaContext + { + get { return _xamlContext.SchemaContext; } + } + #endregion + + #region IProvideValueTarget Members + object IProvideValueTarget.TargetObject + { + get { return _xamlContext.ParentInstance; } + } + + object IProvideValueTarget.TargetProperty + { + get { return ContextServices.GetTargetProperty(this._xamlContext); } + } + #endregion + + #region IRootObjectProvider Members + object IRootObjectProvider.RootObject + { + get + { + return _xamlContext.RootInstance; + } + } + #endregion + + #region IXamlNamespaceResolver Members + string IXamlNamespaceResolver.GetNamespace(string prefix) + { + string xns = _xamlContext.FindNamespaceByPrefix(prefix); + return xns; + } + + IEnumerable IXamlNamespaceResolver.GetNamespacePrefixes() + { + return _xamlContext.GetNamespacePrefixes(); + } + #endregion + + #region IXamlNameResolver Members + + bool IXamlNameResolver.IsFixupTokenAvailable + { + get { return !_xamlContext.NameResolutionComplete; } + } + + object IXamlNameResolver.Resolve(string name) + { + bool isFullyInitialized; + return _xamlContext.ResolveName(name, out isFullyInitialized); + } + + object IXamlNameResolver.Resolve(string name, out bool isFullyInitialized) + { + return _xamlContext.ResolveName(name, out isFullyInitialized); + } + + object IXamlNameResolver.GetFixupToken(IEnumerable names) + { + return ((IXamlNameResolver)this).GetFixupToken(names, false); + } + + object IXamlNameResolver.GetFixupToken(IEnumerable names, bool canAssignDirectly) + { + if (_xamlContext.NameResolutionComplete) + { + return null; + } + var token = new NameFixupToken(); + token.CanAssignDirectly = canAssignDirectly; + token.NeededNames.AddRange(names); + if (token.CanAssignDirectly && token.NeededNames.Count != 1) + { + throw new ArgumentException(SR.Get(SRID.SimpleFixupsMustHaveOneName), "names"); + } + + // TypeConverter case (aka "Initialization") + if (_xamlContext.CurrentType == null) + { + // If this is OBJECT Initialization + if (_xamlContext.ParentProperty == XamlLanguage.Initialization) + { + token.FixupType = FixupType.ObjectInitializationValue; + + // If this is object initialization syntax: + // SO Button> + // SM Background + // SO RefObject + // SM _Initialization + // V "_name" + // This TC will return the RefObject and + // The fixup is to Button.Background (the grand parent) + // + token.Target.Instance = _xamlContext.GrandParentInstance; + token.Target.InstanceWasGotten = _xamlContext.GrandParentIsObjectFromMember; + token.Target.InstanceType = _xamlContext.GrandParentType; + token.Target.Property = _xamlContext.GrandParentProperty; + } + else // This is PROPERTY Initialization + { + token.FixupType = FixupType.PropertyValue; + + // If this is Property Value syntax: + // SO TextBox + // SM LabelProp [has a NameRef TypeConverter] + // V "_name" + // The fixup is to TextBox.LabelProp (the parent) + // + token.Target.Instance = _xamlContext.ParentInstance; + token.Target.InstanceWasGotten = _xamlContext.ParentIsObjectFromMember; + token.Target.InstanceType = _xamlContext.ParentType; + token.Target.Property = _xamlContext.ParentProperty; + } + } + else // MarkupExtensions + { + token.FixupType = FixupType.MarkupExtensionRerun; + + token.Target.Instance = _xamlContext.ParentInstance; + token.Target.InstanceWasGotten = _xamlContext.ParentIsObjectFromMember; + token.Target.InstanceType = _xamlContext.ParentType; + token.Target.Property = _xamlContext.ParentProperty; + } + + // We don't need to save a context stack for simple fixups (Assigned Directly). + // This makes them ALOT cheaper. + // [Simple fixups only need the namescope from the stack.] + // + if (token.CanAssignDirectly) + { + token.NameScopeDictionaryList.AddRange(_xamlContext.StackWalkOfNameScopes); + } + else + { + token.SavedContext = _xamlContext.GetSavedContext((token.FixupType == FixupType.MarkupExtensionRerun) + ? SavedContextType.ReparseMarkupExtension + : SavedContextType.ReparseValue); + } + + return token; + } + + + IEnumerable> IXamlNameResolver.GetAllNamesAndValuesInScope() + { + return _xamlContext.GetAllNamesAndValuesInScope(); + } + + event EventHandler IXamlNameResolver.OnNameScopeInitializationComplete + { + add + { + _xamlContext.AddNameScopeInitializationCompleteSubscriber(value); + } + remove + { + + _xamlContext.RemoveNameScopeInitializationCompleteSubscriber(value); + } + } + + #endregion + + #region IDestinationTypeProvider Members + + public Type GetDestinationType() + { + return _xamlContext.GetDestinationType().UnderlyingType; + } + + #endregion + + #region IXamlLineInfo Members + + public bool HasLineInfo + { + get { return _xamlContext.LineNumber != 0 || _xamlContext.LinePosition != 0; } + } + + public int LineNumber + { + get { return _xamlContext.LineNumber; } + } + + public int LinePosition + { + get { return _xamlContext.LinePosition; } + } + + #endregion + + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlCommonFrame.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlCommonFrame.cs new file mode 100644 index 00000000000..78db97a30f2 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlCommonFrame.cs @@ -0,0 +1,97 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using System.Threading; +using System.Xaml; +using System.Xaml.MS.Impl; + +namespace MS.Internal.Xaml.Context +{ + internal abstract class XamlCommonFrame: XamlFrame + { + internal Dictionary _namespaces; + + public Dictionary Namespaces + { + get + { + if (_namespaces == null) + _namespaces = new Dictionary(); + return _namespaces; + } + } + + public XamlCommonFrame() : base() + { + } + + public XamlCommonFrame(XamlCommonFrame source) : base(source) + { + XamlType = source.XamlType; + Member = source.Member; + + if (source._namespaces != null) + { + SetNamespaces(source._namespaces); + } + } + + public override void Reset() + { + XamlType = null; + Member = null; + if (_namespaces != null) + { + _namespaces.Clear(); + } + } + + public XamlType XamlType { get; set; } + public XamlMember Member { get; set; } + + public void AddNamespace(string prefix, string xamlNs) + { + Namespaces.Add(prefix, xamlNs); + } + + public void SetNamespaces(Dictionary namespaces) + { + if (_namespaces != null) + { + _namespaces.Clear(); + } + if (namespaces != null) + { + foreach (KeyValuePair ns in namespaces) + { + Namespaces.Add(ns.Key, ns.Value); + } + } + } + + public bool TryGetNamespaceByPrefix(string prefix, out string xamlNs) + { + if (_namespaces != null && _namespaces.TryGetValue(prefix, out xamlNs)) + { + return true; + } + xamlNs = null; + return false; + } + + public IEnumerable GetNamespacePrefixes() + { + List _namespaceDeclarations = new List(); + foreach (KeyValuePair kvp in _namespaces) + { + _namespaceDeclarations.Add(new NamespaceDeclaration(kvp.Value, kvp.Key)); + } + return _namespaceDeclarations; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlContext.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlContext.cs new file mode 100644 index 00000000000..c552c06b700 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlContext.cs @@ -0,0 +1,381 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ComponentModel; +using System.Collections.Generic; +using System.Reflection; +using System.Diagnostics; +using System.Xaml; +using MS.Internal.Xaml.Context; +using System.Xaml.Schema; +using System.Xaml.MS.Impl; +using MS.Internal.Xaml.Parser; + +namespace MS.Internal.Xaml +{ + internal abstract class XamlContext + { + private XamlSchemaContext _schemaContext; + private Func _resolvePrefixCachedDelegate; + protected Assembly _localAssembly; + + protected XamlContext(XamlSchemaContext schemaContext) + { + _schemaContext = schemaContext; + } + + public XamlSchemaContext SchemaContext + { + get { return _schemaContext; } + } + + /// + /// Note: not SecurityCritical. Should be used only for convenience filtering, not for security decisions. + /// + public virtual Assembly LocalAssembly + { + get + { + return _localAssembly; + } + protected set + { + _localAssembly = value; + } + } + + // Only pass rootObjectType if the member is being looked up on the root object + public XamlMember GetXamlProperty(XamlType xamlType, string propertyName, XamlType rootObjectType) + { + if (xamlType.IsUnknown) + { + return null; + } + XamlMember member = xamlType.GetMember(propertyName); + return IsVisible(member, rootObjectType) ? member : null; + } + + public XamlMember GetXamlAttachableProperty(XamlType xamlType, string propertyName) + { + if (xamlType.IsUnknown) + { + return null; + } + XamlMember member = xamlType.GetAttachableMember(propertyName); + return IsVisible(member, null) ? member : null; + } + + /// + /// Resolves a property of the form 'Foo.Bar' or 'a:Foo.Bar', in + /// in the context of a parent tag. The parent tagType may or may not + /// be covariant with the ownerType. In the case of dotted attribute + /// syntax, the namespace my be passed in. + /// + /// The xamlType of the enclosing Tag + /// The namespace of the enclosing Tag + /// The dotted name of the property + /// Whether the tag is the root of the document + /// + public XamlMember GetDottedProperty(XamlType tagType, string tagNamespace, XamlPropertyName propName, bool tagIsRoot) + { + if (tagType == null) + { + throw new XamlInternalException(SR.Get(SRID.ParentlessPropertyElement, propName.ScopedName)); + } + XamlMember property = null; + XamlType ownerType = null; + string ns = ResolveXamlNameNS(propName); + if (ns == null) + { + throw new XamlParseException(SR.Get(SRID.PrefixNotFound, propName.Prefix)); + } + XamlType rootTagType = tagIsRoot ? tagType : null; + + // If we have we want foo in foo.bar to match the tag + // type since there is no way to specify generic syntax in dotted property notation + // If that fails, then we fall back to the non-generic case below. + bool ownerTypeMatchesGenericTagType = false; + if (tagType.IsGeneric) + { + ownerTypeMatchesGenericTagType = PropertyTypeMatchesGenericTagType(tagType, tagNamespace, ns, propName.OwnerName); + if (ownerTypeMatchesGenericTagType) + { + property = GetInstanceOrAttachableProperty(tagType, propName.Name, rootTagType); + if (property != null) + { + return property; + } + } + } + + // Non-generic case, just resolve using the namespace and name + XamlTypeName ownerTypeName = new XamlTypeName(ns, propName.Owner.Name); + ownerType = this.GetXamlType(ownerTypeName, true); + bool canAssignTagTypeToOwnerType = tagType.CanAssignTo(ownerType); + + if (canAssignTagTypeToOwnerType) + { + property = GetInstanceOrAttachableProperty(ownerType, propName.Name, rootTagType); + } + else + { + property = this.GetXamlAttachableProperty(ownerType, propName.Name); + } + if (property == null) + { + // This is an unknown property. + // We don't know for sure whether or not it's attachable, so we go with our best guess. + // If the owner type is same as the generic tag type, or is assignable to the tag type, + // it's probably not attachable. + XamlType declaringType = ownerTypeMatchesGenericTagType ? tagType : ownerType; + if (ownerTypeMatchesGenericTagType || canAssignTagTypeToOwnerType) + { + property = CreateUnknownMember(declaringType, propName.Name); + } + else + { + property = CreateUnknownAttachableMember(declaringType, propName.Name); + } + } + return property; + } + + public string GetAttributeNamespace(XamlPropertyName propName, string tagNamespace) + { + string ns = null; + + // Get the proper XamlNamespace for the Property + // If prefix is "" then + // Normal Properties resolve to the ownerType namespace + // Attachable properties resolve to the actual "" namespace + if (String.IsNullOrEmpty(propName.Prefix) && !propName.IsDotted) + { + ns = tagNamespace; + } + else + { + ns = ResolveXamlNameNS(propName); + } + return ns; + } + + public XamlMember GetNoDotAttributeProperty(XamlType tagType, XamlPropertyName propName, + string tagNamespace, string propUsageNamespace, bool tagIsRoot) + { + XamlMember property = null; + // workaround: tagNamespace will always be null coming from MeScanner. + // Second line of if just handles tagNamespace always being null from MEScanner + // Correct fix is to fix MEScanner and remove second line + if ((propUsageNamespace == tagNamespace) + || (tagNamespace == null && propUsageNamespace != null && tagType.GetXamlNamespaces().Contains(propUsageNamespace))) + { + XamlType rootTagType = tagIsRoot ? tagType : null; + property = this.GetXamlProperty(tagType, propName.Name, rootTagType); + + // Sometimes Attached properties look like normal properties. + // [Attribute case] The above lookup fails and fall into here. + // + if (property == null) + { + property = this.GetXamlAttachableProperty(tagType, propName.Name); + } + } + // Not Simple, not Attachable, look for Directives. + if (property == null && propUsageNamespace != null) + { + // A processing attribute like; x:Key x:Name + XamlDirective directive = SchemaContext.GetXamlDirective(propUsageNamespace, propName.Name); + if (directive != null) + { + if (AllowedMemberLocations.None == (directive.AllowedLocation & AllowedMemberLocations.Attribute)) + { + // Need a way to surface up this usage error now that + // we don't have UnknownProperty.Exception + directive = new XamlDirective(propUsageNamespace, propName.Name); + } + property = directive; + } + } + if (property == null) + { + if (tagNamespace == propUsageNamespace) + { + // Unknown simple property + property = new XamlMember(propName.Name, tagType, false); + } + else + { + // Unknown directive + property = new XamlDirective(propUsageNamespace, propName.Name); + } + } + return property; + } + + abstract public void AddNamespacePrefix(string prefix, string xamlNamespace); + abstract public string FindNamespaceByPrefix(string prefix); + abstract public IEnumerable GetNamespacePrefixes(); + + + // -------------------- internal ------------------------ + + private XamlType GetXamlTypeOrUnknown(XamlTypeName typeName) + { + return GetXamlType(typeName, true); + } + + internal XamlType GetXamlType(XamlName typeName) + { + return GetXamlType(typeName, false); + } + + internal XamlType GetXamlType(XamlName typeName, bool returnUnknownTypesOnFailure) + { + XamlTypeName fullTypeName = GetXamlTypeName(typeName); + return GetXamlType(fullTypeName, returnUnknownTypesOnFailure); + } + + internal XamlTypeName GetXamlTypeName(XamlName typeName) + { + string xamlNs = ResolveXamlNameNS(typeName); + if (xamlNs == null) + { + throw new XamlParseException(SR.Get(SRID.PrefixNotFound, typeName.Prefix)); + } + return new XamlTypeName(xamlNs, typeName.Name); + } + + internal XamlType GetXamlType(XamlTypeName typeName) + { + return GetXamlType(typeName, false, false); + } + + internal XamlType GetXamlType(XamlTypeName typeName, bool returnUnknownTypesOnFailure) + { + return GetXamlType(typeName, returnUnknownTypesOnFailure, false); + } + + internal XamlType GetXamlType(XamlTypeName typeName, bool returnUnknownTypesOnFailure, + bool skipVisibilityCheck) + { + Debug.Assert(typeName != null, "typeName cannot be null and should have been checked before now"); + Debug.Assert(typeName.Name != null, "typeName.Name cannot be null and should have been checked before now"); + Debug.Assert(typeName.Namespace != null); + XamlType xamlType = _schemaContext.GetXamlType(typeName); + if (xamlType != null && !skipVisibilityCheck && !xamlType.IsVisibleTo(LocalAssembly)) + { + xamlType = null; + } + + if (xamlType == null && returnUnknownTypesOnFailure) + { + XamlType[] typeArgs = null; + if (typeName.HasTypeArgs) + { + typeArgs = ArrayHelper.ConvertArrayType( + typeName.TypeArguments, GetXamlTypeOrUnknown); + } + xamlType = new XamlType(typeName.Namespace, typeName.Name, typeArgs, this.SchemaContext); + } + return xamlType; + } + + internal Func ResolvePrefixCachedDelegate + { + get + { + if (_resolvePrefixCachedDelegate == null) + { + _resolvePrefixCachedDelegate = new Func(FindNamespaceByPrefix); + } + return _resolvePrefixCachedDelegate; + } + } + + private string ResolveXamlNameNS(XamlName name) + { + return name.Namespace ?? FindNamespaceByPrefix(name.Prefix); + } + + internal XamlType ResolveXamlType(string qName, bool skipVisibilityCheck) + { + string error; + XamlTypeName typeName = XamlTypeName.ParseInternal(qName, ResolvePrefixCachedDelegate, out error); + if (typeName == null) + { + throw new XamlParseException(error); + } + return GetXamlType(typeName, false, skipVisibilityCheck); + } + + internal XamlMember ResolveDirectiveProperty(string xamlNS, string name) + { + if (xamlNS != null) + { + return SchemaContext.GetXamlDirective(xamlNS, name); + } + return null; + } + + // Only pass rootObjectType if the member is being looked up on the root object + internal virtual bool IsVisible(XamlMember member, XamlType rootObjectType) + { + return true; + } + + private XamlMember CreateUnknownMember(XamlType declaringType, string name) + { + return new XamlMember(name, declaringType, false); + } + + private XamlMember CreateUnknownAttachableMember(XamlType declaringType, string name) + { + return new XamlMember(name, declaringType, true); + } + + private bool PropertyTypeMatchesGenericTagType(XamlType tagType, string tagNs, string propNs, string propTypeName) + { + // Schema can potentially remap names and namespaces from what is requested in GetXamlType. + // However, a failed GetXamlType call is expensive, we don't want to do one unnecessarily. + // So we try to match the property type to the generic type if: + // - The xml namespaces are an exact match + // - The type names are an exact match + // - The property is in any of the same namespaces as the tag type + if (tagNs != propNs && tagType.Name != propTypeName && + !tagType.GetXamlNamespaces().Contains(propNs)) + { + return false; + } + XamlType propertyType = GetXamlType(propNs, propTypeName, tagType.TypeArguments); + return tagType == propertyType; + } + + private XamlMember GetInstanceOrAttachableProperty(XamlType tagType, string propName, XamlType rootTagType) + { + XamlMember property = this.GetXamlProperty(tagType, propName, rootTagType); + if (property == null) + { + // Sometimes Attached properties look like normal properties. + // The above lookup fails and fall into here. + // ie: 0 + // or: + property = this.GetXamlAttachableProperty(tagType, propName); + } + return property; + } + + private XamlType GetXamlType(string ns, string name, IList typeArguments) + { + XamlType[] typeArgArray = new XamlType[typeArguments.Count]; + typeArguments.CopyTo(typeArgArray, 0); + XamlType xamlType = _schemaContext.GetXamlType(ns, name, typeArgArray); + if (xamlType != null && !xamlType.IsVisibleTo(LocalAssembly)) + { + xamlType = null; + } + return xamlType; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlObjectWriterFactory.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlObjectWriterFactory.cs new file mode 100644 index 00000000000..5815315a014 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlObjectWriterFactory.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Xaml; + +namespace MS.Internal.Xaml.Context +{ + internal class XamlObjectWriterFactory: IXamlObjectWriterFactory + { + XamlSavedContext _savedContext; + XamlObjectWriterSettings _parentSettings; + + public XamlObjectWriterFactory(ObjectWriterContext context) + { + _savedContext = context.GetSavedContext(SavedContextType.Template); + _parentSettings = context.ServiceProvider_GetSettings(); + } + + #region IXamlObjectWriterFactory Members + + public XamlObjectWriter GetXamlObjectWriter(XamlObjectWriterSettings settings) + { + return new XamlObjectWriter(_savedContext, settings); + } + + public XamlObjectWriterSettings GetParentSettings() + { + return new XamlObjectWriterSettings(_parentSettings); + } + + #endregion + + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlParserContext.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlParserContext.cs new file mode 100644 index 00000000000..c9dcc4505f3 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlParserContext.cs @@ -0,0 +1,314 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Reflection; +using System.Xaml; +using XAML3 = System.Windows.Markup; +using System.Xaml.Schema; +using MS.Internal.Xaml.Parser; +using System.Xaml.MS.Impl; +using System.Diagnostics; + +namespace MS.Internal.Xaml.Context +{ + internal class XamlParserContext : XamlContext + { + private XamlContextStack _stack; + private Dictionary _prescopeNamespaces; + + public bool AllowProtectedMembersOnRoot { get; set; } + + public Func XmlNamespaceResolver { get; set; } + + public XamlParserContext(XamlSchemaContext schemaContext, Assembly localAssembly) + :base(schemaContext) + { + _stack = new XamlContextStack(()=>new XamlParserFrame()); + _prescopeNamespaces = new Dictionary(); + base._localAssembly = localAssembly; + } + + // ----- abstracts overriden from XamlContext. + + public override void AddNamespacePrefix(String prefix, string xamlNS) + { + _prescopeNamespaces.Add(prefix, xamlNS); + } + + public string FindNamespaceByPrefixInParseStack(String prefix) + { + string xamlNs; + + if (null != _prescopeNamespaces) + { + if (_prescopeNamespaces.TryGetValue(prefix, out xamlNs)) + { + return xamlNs; + } + } + + XamlParserFrame frame = _stack.CurrentFrame; + while (frame.Depth > 0) + { + if (frame.TryGetNamespaceByPrefix(prefix, out xamlNs)) + { + return xamlNs; + } + frame = (XamlParserFrame)frame.Previous; + } + return null; + } + + public override string FindNamespaceByPrefix(String prefix) + { + // For proper operation of some corner senarios the XmlNamespaceResolver + // must be set. But if it isn't we fall back to a look in our own stack. + // Senarios that REQUIRE an XmlNamespaceResolver + // 1) Prefix defs that ONLY exist in the XmlNsManager are only found this way + // 2) Prefix defs on MarkupCompat Tags have effect but don't appear + // in the Xml node stream the XAML parser sees. + // But for normal XAML the XmlNamespaceResolver does not need to be used. + + if (XmlNamespaceResolver != null) + { + return XmlNamespaceResolver(prefix); + } + return FindNamespaceByPrefixInParseStack(prefix); + } + + public override IEnumerable GetNamespacePrefixes() + { + XamlParserFrame frame = _stack.CurrentFrame; + Dictionary keys = new Dictionary(); + while (frame.Depth > 0) + { + if (frame._namespaces != null) + { + foreach (NamespaceDeclaration namespaceDeclaration in frame.GetNamespacePrefixes()) + { + if (!keys.ContainsKey(namespaceDeclaration.Prefix)) + { + keys.Add(namespaceDeclaration.Prefix, null); + yield return namespaceDeclaration; + } + } + } + frame = (XamlParserFrame)frame.Previous; + } + + if (_prescopeNamespaces != null) + { + foreach (KeyValuePair kvp in _prescopeNamespaces) + { + if (!keys.ContainsKey(kvp.Key)) + { + keys.Add(kvp.Key, null); + yield return new NamespaceDeclaration(kvp.Value, kvp.Key); + } + } + } + } + + // Only pass rootObjectType if the member is being looked up on the root object + internal override bool IsVisible(XamlMember member, XamlType rootObjectType) + { + if (member == null) + { + return false; + } + + Type allowProtectedForType = null; + if (AllowProtectedMembersOnRoot && rootObjectType != null) + { + allowProtectedForType = rootObjectType.UnderlyingType; + } + + // First check if the property setter is visible + if (member.IsWriteVisibleTo(LocalAssembly, allowProtectedForType)) + { + return true; + } + + // If the property setter is not visible, but the property getter is, treat the property + // as if it were read-only + if (member.IsReadOnly || (member.Type != null && member.Type.IsUsableAsReadOnly)) + { + return member.IsReadVisibleTo(LocalAssembly, allowProtectedForType); + } + + return false; + } + + // ----- new public methods. + + public void PushScope() + { + _stack.PushScope(); + if (_prescopeNamespaces.Count > 0) + { + _stack.CurrentFrame.SetNamespaces(_prescopeNamespaces); + _prescopeNamespaces = new Dictionary(); + } + } + + public void PopScope() + { + _stack.PopScope(); + } + + internal void InitBracketCharacterCacheForType(XamlType extensionType) + { + CurrentEscapeCharacterMapForMarkupExtension = SchemaContext.InitBracketCharacterCacheForType(extensionType); + } + + /// + /// Finds the list of parameters of the constructor with the most number + /// of arguments. + /// + internal void InitLongestConstructor(XamlType xamlType) + { + IEnumerable constructors = xamlType.GetConstructors(); + ParameterInfo[] constructorParameters = null; + int parameterCount = 0; + foreach (ConstructorInfo ctr in constructors) + { + ParameterInfo[] parInfo = ctr.GetParameters(); + if (parInfo.Length >= parameterCount) + { + parameterCount = parInfo.Length; + constructorParameters = parInfo; + } + } + + CurrentLongestConstructorOfMarkupExtension = constructorParameters; + } + + // FxCop says this is never called + //public int Depth + //{ + // get { return _stack.Depth; } + //} + + public XamlType CurrentType + { + get { return _stack.CurrentFrame.XamlType; } + set { _stack.CurrentFrame.XamlType = value; } + } + + internal BracketModeParseParameters CurrentBracketModeParseParameters + { + get { return _stack.CurrentFrame.BracketModeParseParameters; } + set { _stack.CurrentFrame.BracketModeParseParameters = value; } + } + + internal ParameterInfo[] CurrentLongestConstructorOfMarkupExtension + { + get { return _stack.CurrentFrame.LongestConstructorOfCurrentMarkupExtensionType; } + set { _stack.CurrentFrame.LongestConstructorOfCurrentMarkupExtensionType = value; } + } + + internal Dictionary CurrentEscapeCharacterMapForMarkupExtension + { + get { return _stack.CurrentFrame.EscapeCharacterMapForMarkupExtension; } + set { _stack.CurrentFrame.EscapeCharacterMapForMarkupExtension = value; } + } + + // This property refers to a namespace specified explicitly in the XAML document. + // If this is an implicit type (e.g. GO, x:Data, implicit array) just leave it as null. + public string CurrentTypeNamespace + { + get { return _stack.CurrentFrame.TypeNamespace; } + set { _stack.CurrentFrame.TypeNamespace = value; } + } + + public bool CurrentInContainerDirective + { + get { return _stack.CurrentFrame.InContainerDirective; } + set { _stack.CurrentFrame.InContainerDirective = value; } + } + + // FxCop says this is not called + //public XamlType ParentType + //{ + // get { return _stack.PreviousFrame.XamlType; } + //} + + public XamlMember CurrentMember + { + get { return _stack.CurrentFrame.Member; } + set { _stack.CurrentFrame.Member = value; } + } + + // FxCop says this is not called + //public XamlProperty MemberProperty + //{ + // get { return _stack.PreviousFrame.Member; } + //} + + public int CurrentArgCount + { + get { return _stack.CurrentFrame.CtorArgCount; } + set { _stack.CurrentFrame.CtorArgCount = value; } + } + + public bool CurrentForcedToUseConstructor + { + get { return _stack.CurrentFrame.ForcedToUseConstructor; } + set { _stack.CurrentFrame.ForcedToUseConstructor = value; } + } + + public bool CurrentInItemsProperty + { + get { return _stack.CurrentFrame.Member == XamlLanguage.Items; } + } + + public bool CurrentInInitProperty + { + get { return _stack.CurrentFrame.Member == XamlLanguage.Initialization; } + } + + public bool CurrentInUnknownContent + { + get { return _stack.CurrentFrame.Member == XamlLanguage.UnknownContent; } + } + + public bool CurrentInImplicitArray + { + get { return _stack.CurrentFrame.InImplicitArray; } + set { _stack.CurrentFrame.InImplicitArray = value; } + } + + public bool CurrentInCollectionFromMember + { + get { return _stack.CurrentFrame.InCollectionFromMember; } + set { _stack.CurrentFrame.InCollectionFromMember = value; } + } + + public XamlType CurrentPreviousChildType + { + get { return _stack.CurrentFrame.PreviousChildType; } + set { _stack.CurrentFrame.PreviousChildType = value; } + } + + public bool CurrentMemberIsWriteVisible() + { + Type allowProtectedForType = null; + if (AllowProtectedMembersOnRoot && _stack.Depth == 1) + { + allowProtectedForType = CurrentType.UnderlyingType; + } + return CurrentMember.IsWriteVisibleTo(LocalAssembly, allowProtectedForType); + } + + public bool CurrentTypeIsRoot + { + get { return _stack.CurrentFrame.XamlType != null && _stack.Depth == 1; } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlParserFrame.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlParserFrame.cs new file mode 100644 index 00000000000..575213adf5a --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Context/XamlParserFrame.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using System.Reflection; +using System.Xaml; +using System.Xaml.MS.Impl; +using MS.Internal.Xaml.Parser; + +namespace MS.Internal.Xaml.Context +{ + internal class XamlParserFrame: XamlCommonFrame + { + public override void Reset() + { + base.Reset(); + PreviousChildType = null; + CtorArgCount = 0; + ForcedToUseConstructor = false; + InCollectionFromMember = false; + InImplicitArray = false; + InContainerDirective = false; + TypeNamespace = null; + LongestConstructorOfCurrentMarkupExtensionType = null; + EscapeCharacterMapForMarkupExtension = null; + BracketModeParseParameters = null; + } + + public XamlType PreviousChildType { get; set; } + public int CtorArgCount { get; set; } + public bool ForcedToUseConstructor { get; set; } + public bool InCollectionFromMember { get; set; } + public bool InImplicitArray { get; set; } + public bool InContainerDirective { get; set; } + public string TypeNamespace { get; set; } + public ParameterInfo[] LongestConstructorOfCurrentMarkupExtensionType { get; set; } + public Dictionary EscapeCharacterMapForMarkupExtension { get; set; } + public BracketModeParseParameters BracketModeParseParameters { get; set; } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/EventConverter.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/EventConverter.cs new file mode 100644 index 00000000000..13a7f52ab37 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/EventConverter.cs @@ -0,0 +1,71 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Xaml.Schema; + +namespace System.Xaml +{ + internal class EventConverter : TypeConverter + { + // CanConvertTo and ConvertTo are not implemented here because it is not possible to convert + // an event/delegate to string in the general case, because + // 1. an event's getter is private. + // 2. we currently do not have a syntax for writing down a multi-cast delegate + // 3. we currently do not have a syntax to write down a method not on the root object. + + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + { + return true; + } + return base.CanConvertFrom(context, sourceType); + } + + public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) + { + string valueString = value as string; + if (valueString != null) + { + object rootObject = null; + Type delegateType = null; + GetRootObjectAndDelegateType(context, out rootObject, out delegateType); + + if (rootObject != null && delegateType != null) + { + return SafeReflectionInvoker.CreateDelegate(delegateType, rootObject, valueString); + } + } + return base.ConvertFrom(context, culture, value); + } + + internal static void GetRootObjectAndDelegateType(ITypeDescriptorContext context, out object rootObject, out Type delegateType) + { + rootObject = null; + delegateType = null; + + if (context == null) + { + return; + } + + IRootObjectProvider rootObjectService = context.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider; + if (rootObjectService == null) + { + return; + } + rootObject = rootObjectService.RootObject; + + IDestinationTypeProvider targetService = context.GetService(typeof(IDestinationTypeProvider)) as IDestinationTypeProvider; + if (targetService == null) + { + return; + } + delegateType = targetService.GetDestinationType(); + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Events/ObjectCreatedEventArgs.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Events/ObjectCreatedEventArgs.cs new file mode 100644 index 00000000000..2fcbf5be199 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Events/ObjectCreatedEventArgs.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +#if SILVERLIGHTXAML +namespace MS.Internal.Xaml +#else +namespace System.Xaml +#endif +{ + public class XamlCreatedObjectEventArgs : EventArgs + { + public XamlCreatedObjectEventArgs(Object createdObject) + { + if (createdObject == null) + { + throw new ArgumentNullException("createdObject"); + } + + CreatedObject = createdObject; + } + + public Object CreatedObject { get; private set; } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Events/XamlObjectEventArgs.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Events/XamlObjectEventArgs.cs new file mode 100644 index 00000000000..acfe78e25dd --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Events/XamlObjectEventArgs.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Xaml +{ + public class XamlObjectEventArgs : EventArgs + { + public XamlObjectEventArgs(object instance) + { + if (instance == null) + { + throw new ArgumentNullException("instance"); + } + + Instance = instance; + } + + internal XamlObjectEventArgs(object instance, Uri sourceBamlUri, int elementLineNumber, int elementLinePosition) : + this(instance) + { + SourceBamlUri = sourceBamlUri; + ElementLineNumber = elementLineNumber; + ElementLinePosition = elementLinePosition; + } + + public object Instance { get; private set; } + + public Uri SourceBamlUri { get; private set; } + + public int ElementLineNumber { get; private set; } + + public int ElementLinePosition { get; private set; } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IAmbientProvider.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IAmbientProvider.cs new file mode 100644 index 00000000000..0877937010e --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IAmbientProvider.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Xaml +{ + public interface IAmbientProvider + { + AmbientPropertyValue GetFirstAmbientValue(IEnumerable ceilingTypes, + params XamlMember[] properties); + object GetFirstAmbientValue(params XamlType[] types); + + IEnumerable GetAllAmbientValues(IEnumerable ceilingTypes, + params XamlMember[] properties); + + IEnumerable GetAllAmbientValues(params XamlType[] types); + + IEnumerable GetAllAmbientValues(IEnumerable ceilingTypes, + bool searchLiveStackOnly, + IEnumerable types, + params XamlMember[] properties); + } + + public class AmbientPropertyValue + { + XamlMember _property; + object _value; + + public AmbientPropertyValue(XamlMember property, object value) + { + _property = property; + _value = value; + } + + public object Value { get { return _value; } } + public XamlMember RetrievedProperty { get { return _property; } } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IAttachedPropertyStore.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IAttachedPropertyStore.cs new file mode 100644 index 00000000000..4d2f0b9d211 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IAttachedPropertyStore.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Xaml +{ + using System.Diagnostics.CodeAnalysis; + using System.Collections.Generic; + using System.Xaml; + + public interface IAttachedPropertyStore + { + // The number of properties currently attached to this instance + int PropertyCount + { get; } + + // Retrieve the set of attached properties for this instance. This is + // a copy of the current set of properties. + void CopyPropertiesTo(KeyValuePair[] array, int index); + // Remove the property 'name' from this instance. If the property doesn't + // currently exist this returns false. + bool RemoveProperty(AttachableMemberIdentifier attachableMemberIdentifier); + // Set the property 'name' to 'value' for this instance. If the property + // doesn't currently exist on this instance it will be created. + void SetProperty(AttachableMemberIdentifier attachableMemberIdentifier, object value); + // Retrieve the value of the attached property 'name' for this instance. + // If there is not an attached property defined for this instance with + // this 'name' then returns false. If the value of the attached property + // for this instance with this 'name' cannot be cast to T then returns + // false. + [SuppressMessage("Microsoft.Design", "CA1007")] + bool TryGetProperty(AttachableMemberIdentifier attachableMemberIdentifier, out object value); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IDestinationTypeProvider.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IDestinationTypeProvider.cs new file mode 100644 index 00000000000..761c7d9f9cb --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IDestinationTypeProvider.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace System.Xaml +{ + public interface IDestinationTypeProvider + { + Type GetDestinationType(); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/INamespacePrefixLookup.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/INamespacePrefixLookup.cs new file mode 100644 index 00000000000..a24a776abaf --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/INamespacePrefixLookup.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Xaml +{ + public interface INamespacePrefixLookup + { + string LookupPrefix(string ns); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IRootObjectProvider.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IRootObjectProvider.cs new file mode 100644 index 00000000000..bc13816d9cb --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IRootObjectProvider.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Xaml +{ + public interface IRootObjectProvider + { + object RootObject { get; } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlLineInfo.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlLineInfo.cs new file mode 100644 index 00000000000..09b4471f903 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlLineInfo.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Xaml +{ + public interface IXamlLineInfo + { + bool HasLineInfo { get; } + + int LineNumber { get; } + int LinePosition { get; } + } + +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlLineInfoConsumer.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlLineInfoConsumer.cs new file mode 100644 index 00000000000..6b5cb26375d --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlLineInfoConsumer.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Xaml +{ + public interface IXamlLineInfoConsumer + { + void SetLineInfo(int lineNumber, int linePosition); + bool ShouldProvideLineInfo { get; } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlNameProvider.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlNameProvider.cs new file mode 100644 index 00000000000..ac51c3ca0ae --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlNameProvider.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace System.Xaml +{ + public interface IXamlNameProvider + { + string GetName(object value); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlNameResolver.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlNameResolver.cs new file mode 100644 index 00000000000..2a9141de808 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlNameResolver.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Markup; +using System.ComponentModel; + +namespace System.Xaml +{ + public interface IXamlNameResolver + { + /// + /// Returns true if GetFixupToken is implemented and will return a non-null token + /// when called at this time. For example GetFixupToken will not return a token + /// when the Type Converter or Markup Extension is called for the second reparse. + /// + bool IsFixupTokenAvailable { get; } + + /// + /// Returns a reference to the named object. + /// + /// name of object + /// + object Resolve(string name); + + /// + /// Returns a reference to the named object. + /// + /// name of object + /// whether or not the object has any dependencies on unresolved references + /// + object Resolve(string name, out bool isFullyInitialized); + + /// + /// Creates a token for a Type Converter or Markup Extension to return when called + /// from the System, for the currently unresolvable names. When all the forward + /// referenced names are resolvable the user code will be called back for a "reparse". + /// + /// currently unresolvable names + /// + object GetFixupToken(IEnumerable names); + + /// + /// Creates a token for a Type Converter or Markup Extension to return when called + /// from the System, for the currently unresolvable names. When all the forward + /// referenced names are resolvable the user code will be called back for a "reparse". + /// + /// currently unresolvable (forward reference) names + /// If true, do not call the user code for a reparse, + /// instead immediately assign the resolved name reference to the target property + /// + object GetFixupToken(IEnumerable names, bool canAssignDirectly); + + IEnumerable> GetAllNamesAndValuesInScope(); + + event EventHandler OnNameScopeInitializationComplete; + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlNamespaceResolver.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlNamespaceResolver.cs new file mode 100644 index 00000000000..301ba93f9f2 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlNamespaceResolver.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Xaml +{ + public interface IXamlNamespaceResolver + { + string GetNamespace(string prefix); + IEnumerable GetNamespacePrefixes(); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlObjectWriterFactory.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlObjectWriterFactory.cs new file mode 100644 index 00000000000..c1ba23562eb --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlObjectWriterFactory.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Markup; +using System.ComponentModel; + +namespace System.Xaml +{ + public interface IXamlObjectWriterFactory + { + XamlObjectWriterSettings GetParentSettings(); + + XamlObjectWriter GetXamlObjectWriter(XamlObjectWriterSettings settings); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlSavedContextProvider.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlSavedContextProvider.cs new file mode 100644 index 00000000000..0cd709ca45a --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlSavedContextProvider.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Xaml +{ + public interface IXamlSavedContextProvider + { + XamlSavedContext GetSavedContext(); + XamlSavedContext GetSavedContext(object instance); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlSchemaContextProvider.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlSchemaContextProvider.cs new file mode 100644 index 00000000000..449ede2c959 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlSchemaContextProvider.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Xaml +{ + public interface IXamlSchemaContextProvider + { + XamlSchemaContext SchemaContext { get; } + } + +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlTemplate.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlTemplate.cs new file mode 100644 index 00000000000..a53a50205ec --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/IXamlTemplate.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +using System.Text; + +#if SILVERLIGHTXAML +namespace MS.Internal.Xaml +#else +namespace System.Xaml +#endif +{ +#if SILVERLIGHTXAML + internal +#else + public +#endif + interface IXamlTemplate + { + void RecordXaml(XamlReader reader, XamlSavedContext templateContext); + XamlReader PlayXaml(); + XamlSavedContext TemplateContext { get; } + } + +#if SILVERLIGHTXAML + internal +#else + public +#endif + interface IXamlTemplate: IXamlTemplate + { + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/DeferredWriter.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/DeferredWriter.cs new file mode 100644 index 00000000000..88db6d74a82 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/DeferredWriter.cs @@ -0,0 +1,327 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using MS.Internal.Xaml.Context; +using System.Xaml.Schema; +using System.Xaml.MS.Impl; + +namespace System.Xaml +{ + internal enum DeferringMode + { + Off, + TemplateStarting, + TemplateDeferring, + TemplateReady, + } + + internal class DeferringWriter : XamlWriter, IXamlLineInfoConsumer + { + DeferringMode _mode; + bool _handled; + ObjectWriterContext _context; + XamlNodeList _deferredList; + XamlWriter _deferredWriter; + IXamlLineInfoConsumer _deferredLineInfoConsumer; + int _deferredTreeDepth; + + public DeferringWriter(ObjectWriterContext context) + { + _context = context; + _mode = DeferringMode.Off; + } + + public void Clear() + { + _handled = false; + _mode = DeferringMode.Off; + _deferredList = null; + _deferredTreeDepth = -1; + } + + public bool Handled + { + get { return _handled; } + } + + public DeferringMode Mode + { + get { return _mode; } + } + + public XamlNodeList CollectTemplateList() + { + XamlNodeList retValue = _deferredList; + _deferredList = null; + _mode = DeferringMode.Off; + return retValue; + } + + #region XamlWriter Members + + public override void WriteGetObject() + { + WriteObject(null, true, "WriteGetObject"); + } + + public override void WriteStartObject(XamlType xamlType) + { + WriteObject(xamlType, false, "WriteStartObject"); + } + + void WriteObject(XamlType xamlType, bool fromMember, string methodName) + { + _handled = false; + switch (_mode) + { + case DeferringMode.Off: + break; + + case DeferringMode.TemplateReady: + throw new XamlInternalException(SR.Get(SRID.TemplateNotCollected, methodName)); + + case DeferringMode.TemplateStarting: + StartDeferredList(); + _mode = DeferringMode.TemplateDeferring; + goto case DeferringMode.TemplateDeferring; + + case DeferringMode.TemplateDeferring: + if (fromMember) + { + _deferredWriter.WriteGetObject(); + } + else + { + _deferredWriter.WriteStartObject(xamlType); + } + _deferredTreeDepth += 1; + _handled = true; + break; + + default: + throw new XamlInternalException(SR.Get(SRID.MissingCase, _mode.ToString(), methodName)); + } + } + + public override void WriteEndObject() + { + _handled = false; + switch (_mode) + { + case DeferringMode.Off: + break; + + case DeferringMode.TemplateReady: + throw new XamlInternalException(SR.Get(SRID.TemplateNotCollected, "WriteEndObject")); + + case DeferringMode.TemplateDeferring: + _deferredWriter.WriteEndObject(); + _handled = true; + _deferredTreeDepth -= 1; + + if (_deferredTreeDepth == 0) + { + _deferredWriter.Close(); + _deferredWriter = null; + _mode = DeferringMode.TemplateReady; + } + break; + + default: + throw new XamlInternalException(SR.Get(SRID.MissingCase, _mode.ToString(), "WriteEndObject")); + } + } + + public override void WriteStartMember(XamlMember property) + { + _handled = false; + switch (_mode) + { + case DeferringMode.Off: + if (property.DeferringLoader != null) + { + _mode = DeferringMode.TemplateStarting; + + // We assume in WriteValue that this property can never be multi-valued + Debug.Assert(!property.IsDirective && !property.IsUnknown); + } + break; + + case DeferringMode.TemplateReady: + throw new XamlInternalException(SR.Get(SRID.TemplateNotCollected, "WriteMember")); + + case DeferringMode.TemplateDeferring: + _deferredWriter.WriteStartMember(property); + _handled = true; + break; + + default: + throw new XamlInternalException(SR.Get(SRID.MissingCase, _mode.ToString(), "WriteMember")); + } + } + + public override void WriteEndMember() + { + _handled = false; + switch (_mode) + { + case DeferringMode.Off: + break; + + case DeferringMode.TemplateReady: + throw new XamlInternalException(SR.Get(SRID.TemplateNotCollected, "WriteEndMember")); + + case DeferringMode.TemplateDeferring: + _deferredWriter.WriteEndMember(); + _handled = true; + break; + + default: + throw new XamlInternalException(SR.Get(SRID.MissingCase, _mode.ToString(), "WriteEndMember")); + } + } + + public override void WriteValue(object value) + { + _handled = false; + switch (_mode) + { + case DeferringMode.Off: + break; + + case DeferringMode.TemplateReady: + throw new XamlInternalException(SR.Get(SRID.TemplateNotCollected, "WriteValue")); + + case DeferringMode.TemplateStarting: + // This handles the case of SM template; V object; EM + Debug.Assert(_deferredTreeDepth == 0); + if (value is XamlNodeList) + { + _deferredList = (XamlNodeList)value; + _mode = DeferringMode.TemplateReady; + _handled = true; + } + else + { + StartDeferredList(); + _mode = DeferringMode.TemplateDeferring; + goto case DeferringMode.TemplateDeferring; + } + break; + + case DeferringMode.TemplateDeferring: + _deferredWriter.WriteValue(value); + _handled = true; + break; + + default: + throw new XamlInternalException(SR.Get(SRID.MissingCase, _mode.ToString(), "WriteValue")); + } + } + + public override void WriteNamespace(NamespaceDeclaration namespaceDeclaration) + { + switch (_mode) + { + case DeferringMode.Off: + return; + + case DeferringMode.TemplateReady: + throw new XamlInternalException(SR.Get(SRID.TemplateNotCollected, "WriteNamespace")); + + case DeferringMode.TemplateStarting: + StartDeferredList(); + _mode = DeferringMode.TemplateDeferring; + goto case DeferringMode.TemplateDeferring; + + case DeferringMode.TemplateDeferring: + _deferredWriter.WriteNamespace(namespaceDeclaration); + _handled = true; + break; + + default: + throw new XamlInternalException(SR.Get(SRID.MissingCase, _mode.ToString(), "WriteNamespace")); + } + } + + protected override void Dispose(bool disposing) + { + try + { + if (disposing && !IsDisposed) + { + if (_deferredWriter != null) + { + _deferredWriter.Close(); + _deferredWriter = null; + _deferredLineInfoConsumer = null; + } + } + } + finally + { + base.Dispose(disposing); + } + } + + public override XamlSchemaContext SchemaContext + { + get { return _context.SchemaContext; } + } + + #endregion + + #region IXamlLineInfoConsumer Members + + public void SetLineInfo(int lineNumber, int linePosition) + { + switch (_mode) + { + case DeferringMode.Off: + return; + + case DeferringMode.TemplateReady: + throw new XamlInternalException(SR.Get(SRID.TemplateNotCollected, nameof(SetLineInfo))); + + case DeferringMode.TemplateStarting: + StartDeferredList(); + // do not change _mode here - only the XamlWriter members should do that + goto case DeferringMode.TemplateDeferring; + + case DeferringMode.TemplateDeferring: + if (_deferredLineInfoConsumer != null) + { + _deferredLineInfoConsumer.SetLineInfo(lineNumber, linePosition); + } + break; + + default: + throw new XamlInternalException(SR.Get(SRID.MissingCase, _mode.ToString(), nameof(SetLineInfo))); + } + } + + public bool ShouldProvideLineInfo + { + get { return true; } + } + + #endregion + + private void StartDeferredList() + { + // the list may have been created already by SetLineInfo + if (_deferredList == null) + { + _deferredList = new XamlNodeList(_context.SchemaContext); + _deferredWriter = _deferredList.Writer; + _deferredLineInfoConsumer = _deferredWriter as IXamlLineInfoConsumer; + _deferredTreeDepth = 0; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/ObjectWriterSettings.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/ObjectWriterSettings.cs new file mode 100644 index 00000000000..9fc7f40d47f --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/ObjectWriterSettings.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Xaml +{ +#if SILVERLIGHTXAML + internal +#else + public +#endif + class ObjectWriterSettings + { + public EventHandler ObjectCreatedHandler { get; set; } + public Object RootObjectInstance { get; set; } + public bool IgnoreCanConvert { get; set; } + public System.Windows.Markup.INameScope NameScope { get; set; } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlNodes.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlNodes.cs new file mode 100644 index 00000000000..b251c3c9177 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlNodes.cs @@ -0,0 +1,274 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Globalization; + +namespace System.Xaml +{ + public enum XamlNodeType:byte + { + None, // need something to return when un-inited. (and past Eof) + StartObject, + GetObject, + EndObject, + StartMember, + EndMember, + Value, + NamespaceDeclaration, + }; + + internal delegate void XamlNodeAddDelegate(XamlNodeType nodeType, object data); + internal delegate void XamlLineInfoAddDelegate(int lineNumber, int linePosition); + internal delegate XamlNode XamlNodeNextDelegate(); + internal delegate XamlNode XamlNodeIndexDelegate(int idx); + + [DebuggerDisplay("{ToString()}")] + internal struct XamlNode + { + internal enum InternalNodeType:byte { None, StartOfStream, EndOfStream, EndOfAttributes, LineInfo } + + XamlNodeType _nodeType; + InternalNodeType _internalNodeType; + private object _data; + + public XamlNodeType NodeType + { + get { return _nodeType; } + } + + public XamlNode(XamlNodeType nodeType) + { +#if DEBUG + switch (nodeType) + { + case XamlNodeType.EndObject: + case XamlNodeType.EndMember: + case XamlNodeType.GetObject: + break; + + default: + Debug.Assert(false, "XamlNode Ctor missing data argument"); + break; + } +#endif + _nodeType = nodeType; + _internalNodeType = InternalNodeType.None; + _data = null; + } + + public XamlNode(XamlNodeType nodeType, object data) + { +#if DEBUG + switch(nodeType) + { + case XamlNodeType.StartObject: + Debug.Assert(data is XamlType, "XamlNode ctor, StartObject data is not a XamlType"); + break; + + case XamlNodeType.StartMember: + Debug.Assert(data is XamlMember, "XamlNode ctor, StartMember data is not a XamlMember"); + break; + + case XamlNodeType.NamespaceDeclaration: + Debug.Assert(data is NamespaceDeclaration, "XamlNode ctor, NamespaceDeclaration data is not a NamespaceDeclaration"); + break; + + case XamlNodeType.Value: + // can be anything; + break; + + case XamlNodeType.EndObject: + case XamlNodeType.EndMember: + case XamlNodeType.GetObject: + Debug.Assert(data == null, "XamlNode ctor, Internal XamlNode data must be null for this Node type"); + break; + + default: + Debug.Assert(false, "XamlNode ctor, incorrect ctor called."); + break; + } +#endif + _nodeType = nodeType; + _internalNodeType = InternalNodeType.None; + _data = data; + } + + public XamlNode(InternalNodeType internalNodeType) + { + Debug.Assert(internalNodeType == InternalNodeType.EndOfAttributes || + internalNodeType == InternalNodeType.StartOfStream || + internalNodeType == InternalNodeType.EndOfStream, "XamlNode ctor: Illegal Internal node type"); + _nodeType = XamlNodeType.None; + _internalNodeType = internalNodeType; + _data = null; + } + + public XamlNode(LineInfo lineInfo) + { + _nodeType = XamlNodeType.None; + _internalNodeType = InternalNodeType.LineInfo; + _data = lineInfo; + } + + public override string ToString() + { + string str = String.Format(TypeConverterHelper.InvariantEnglishUS, "{0}: ", this.NodeType); + switch(NodeType) + { + case XamlNodeType.StartObject: + str += XamlType.Name; + break; + + case XamlNodeType.StartMember: + str += Member.Name; + break; + + case XamlNodeType.Value: + str += Value.ToString(); + break; + + case XamlNodeType.NamespaceDeclaration: + str += NamespaceDeclaration.ToString(); + break; + + case XamlNodeType.None: + switch(_internalNodeType) + { + case InternalNodeType.EndOfAttributes: + str += "End Of Attributes"; + break; + + case InternalNodeType.StartOfStream: + str += "Start Of Stream"; + break; + + case InternalNodeType.EndOfStream: + str += "End Of Stream"; + break; + + case InternalNodeType.LineInfo: + str += "LineInfo: " + LineInfo.ToString(); + break; + } + break; + } + return str; + } + + public NamespaceDeclaration NamespaceDeclaration + { + get + { + if (NodeType == XamlNodeType.NamespaceDeclaration) + { + return (NamespaceDeclaration)_data; + } + return null; + } + } + + public XamlType XamlType + { + get + { + if (NodeType == XamlNodeType.StartObject) + { + return (XamlType)_data; + } + return null; + } + } + + public object Value + { + get + { + if (NodeType == XamlNodeType.Value) + { + return _data; + } + return null; + } + } + + public XamlMember Member + { + get + { + if (NodeType == XamlNodeType.StartMember) + { + return (XamlMember)_data; + } + return null; + } + } + + public LineInfo LineInfo + { + get + { + if (NodeType == XamlNodeType.None) + { + return _data as LineInfo; // might be null for EOF and EOA. + } + return null; + } + } + + internal bool IsEof + { + get + { + if (NodeType == XamlNodeType.None && _internalNodeType == InternalNodeType.EndOfStream) + { + return true; + } + return false; + } + } + + internal bool IsEndOfAttributes + { + get + { + if (NodeType == XamlNodeType.None && _internalNodeType == InternalNodeType.EndOfAttributes) + { + return true; + } + return false; + } + } + + internal bool IsLineInfo + { + get + { + if (NodeType == XamlNodeType.None && _internalNodeType == InternalNodeType.LineInfo) + { + return true; + } + return false; + } + } + + internal static bool IsEof_Helper(XamlNodeType nodeType, object data) + { + if (nodeType != XamlNodeType.None) + { + return false; + } + if (data is InternalNodeType) + { + InternalNodeType internalNodeType = (InternalNodeType)data; + if (internalNodeType == InternalNodeType.EndOfStream) + { + return true; + } + } + return false; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlObjectWriter.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlObjectWriter.cs new file mode 100644 index 00000000000..d981fd9154c --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlObjectWriter.cs @@ -0,0 +1,2694 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using XAML3 = System.Windows.Markup; +using System.ComponentModel; +using System.IO; +using System.Security; +using System.Text; +using MS.Internal.Xaml.Context; +using MS.Internal.Xaml.Runtime; +using System.Xaml.Schema; +using System.Xaml.MS.Impl; +using MS.Internal.Xaml.Parser; +using System.Windows.Markup; +using System.Globalization; + + +namespace System.Xaml +{ + public class XamlObjectWriter : XamlWriter, IXamlLineInfoConsumer, IAddLineInfo, ICheckIfInitialized + { + object _lastInstance; + bool _inDispose; + ObjectWriterContext _context; + DeferringWriter _deferringWriter; + private EventHandler _afterBeginInitHandler; + private EventHandler _beforePropertiesHandler; + private EventHandler _afterPropertiesHandler; + private EventHandler _afterEndInitHandler; +#if !TARGETTING35SP1 + private EventHandler _xamlSetValueHandler; +#endif + private object _rootObjectInstance; + private bool _skipDuplicatePropertyCheck; + NameFixupGraph _nameFixupGraph; + private Dictionary> _pendingCollectionAdds; + INameScope _rootNamescope; + bool _skipProvideValueOnRoot; + bool _nextNodeMustBeEndMember; + bool _preferUnconvertedDictionaryKeys; + private Dictionary _pendingKeyConversionContexts; + +#if DEBUG + private bool _inNameResolution; +#endif + + public XamlObjectWriter(XamlSchemaContext schemaContext) + { + if (schemaContext == null) + { + throw new ArgumentNullException("schemaContext"); + } + Initialize(schemaContext, (XamlSavedContext)null, (XamlObjectWriterSettings)null); + } + + public XamlObjectWriter(XamlSchemaContext schemaContext, XamlObjectWriterSettings settings) + { + if (schemaContext == null) + { + throw new ArgumentNullException("schemaContext"); + } + Initialize(schemaContext, (XamlSavedContext)null, settings); + } + + internal XamlObjectWriter(XamlSavedContext savedContext, XamlObjectWriterSettings settings) + { + if (savedContext == null) + { + throw new ArgumentNullException("savedContext"); + } + if (savedContext.SchemaContext == null) + { + throw new ArgumentException(SR.Get(SRID.SavedContextSchemaContextNull), "savedContext"); + } + Initialize(savedContext.SchemaContext, savedContext, settings); + } + + void Initialize(XamlSchemaContext schemaContext, XamlSavedContext savedContext, XamlObjectWriterSettings settings) + { + _inDispose = false; + //ObjectWriter must be passed in a non-null SchemaContext. We check that here, since the CreateContext method + //will create one if a null SchemaContext was passed in. + if (schemaContext == null) + { + throw new ArgumentNullException("schemaContext"); + } + if (savedContext != null && schemaContext != savedContext.SchemaContext) + { + throw new ArgumentException(SR.Get(SRID.SavedContextSchemaContextMismatch), "schemaContext"); + } + + if (settings != null) + { + _afterBeginInitHandler = settings.AfterBeginInitHandler; + _beforePropertiesHandler = settings.BeforePropertiesHandler; + _afterPropertiesHandler = settings.AfterPropertiesHandler; + _afterEndInitHandler = settings.AfterEndInitHandler; +#if !TARGETTING35SP1 + _xamlSetValueHandler = settings.XamlSetValueHandler; +#endif + _rootObjectInstance = settings.RootObjectInstance; + _skipDuplicatePropertyCheck = settings.SkipDuplicatePropertyCheck; + _skipProvideValueOnRoot = settings.SkipProvideValueOnRoot; + _preferUnconvertedDictionaryKeys = settings.PreferUnconvertedDictionaryKeys; + } + + INameScope rootNameScope = (settings != null) ? settings.ExternalNameScope : null; + + XamlRuntime runtime = CreateRuntime(settings, schemaContext); + + if (savedContext != null) + { + _context = new ObjectWriterContext(savedContext, settings, rootNameScope, runtime); + } + else if (schemaContext != null) + { + _context = new ObjectWriterContext(schemaContext, settings, rootNameScope, runtime); + _context.AddNamespacePrefix(KnownStrings.XmlPrefix, XamlLanguage.Xml1998Namespace); + } + else + { + throw _context.WithLineInfo(new XamlInternalException()); + } + _context.IsInitializedCallback = this; + + _deferringWriter = new DeferringWriter(_context); + _rootNamescope = null; + } + + private XamlRuntime CreateRuntime(XamlObjectWriterSettings settings, XamlSchemaContext schemaContext) + { + XamlRuntime result = null; + XamlRuntimeSettings runtimeSettings = null; + if (settings != null) + { + runtimeSettings = new XamlRuntimeSettings { IgnoreCanConvert = settings.IgnoreCanConvert }; +#if !TARGETTING35SP1 + if (settings.AccessLevel != null) + { + result = new PartialTrustTolerantRuntime(runtimeSettings, settings.AccessLevel, schemaContext); + } + } + if (result == null) + { +#endif + result = new ClrObjectRuntime(runtimeSettings, true /*isWriter*/); + } + result.LineInfo = this; + return result; + } + + protected virtual void OnAfterBeginInit(Object value) + { + if (_afterBeginInitHandler != null) + { + // Currently SourceBamlUri exists only to address pre .NET 4.6 compat issue. It is not + // null only when we load system resources like themes\generic.xaml. And only for + // resources located in RD itself (as opposite to nested RDs). Thus we should never see + // different non-null base and source URIs. In any case base URI is preferred. + Debug.Assert(_context.SourceBamlUri == null || _context.BaseUri == null || _context.SourceBamlUri == _context.BaseUri, + "Source BAML URI and base URI do not agree"); + _afterBeginInitHandler(this, new XamlObjectEventArgs(value, _context.BaseUri ?? _context.SourceBamlUri, _context.LineNumber_StartObject, _context.LinePosition_StartObject)); + } + } + + protected virtual void OnBeforeProperties(Object value) + { + if (_beforePropertiesHandler != null) + { + _beforePropertiesHandler(this, new XamlObjectEventArgs(value)); + } + } + + protected virtual void OnAfterProperties(Object value) + { + if (_afterPropertiesHandler != null) + { + _afterPropertiesHandler(this, new XamlObjectEventArgs(value)); + } + } + + protected virtual void OnAfterEndInit(Object value) + { + if (_afterEndInitHandler != null) + { + _afterEndInitHandler(this, new XamlObjectEventArgs(value)); + } + } + +#if !TARGETTING35SP1 + protected virtual bool OnSetValue(object eventSender, XamlMember member, object value) + { + if (_xamlSetValueHandler != null) + { + var e = new XamlSetValueEventArgs(member, value); + _xamlSetValueHandler(eventSender, e); + return e.Handled; + } + return false; + } +#endif + + private NameFixupGraph NameFixupGraph + { + get + { + if (_nameFixupGraph == null) + { + _nameFixupGraph = new NameFixupGraph(); + } + return _nameFixupGraph; + } + } + + private bool HasUnresolvedChildren(object parent) + { + if (_nameFixupGraph == null) + { + return false; + } + return _nameFixupGraph.HasUnresolvedChildren(parent); + } + + private Dictionary> PendingCollectionAdds + { + get + { + if (_pendingCollectionAdds == null) + _pendingCollectionAdds = new Dictionary>(); + return _pendingCollectionAdds; + } + } + + private Dictionary PendingKeyConversionContexts + { + get + { + if (_pendingKeyConversionContexts == null) + _pendingKeyConversionContexts = new Dictionary(); + return _pendingKeyConversionContexts; + } + } + + private XamlRuntime Runtime + { + get { return _context.Runtime; } + } + + private void TryCreateParentInstance(ObjectWriterContext ctx) + { + if (ctx.ParentInstance == null && ctx.ParentProperty != XamlLanguage.Arguments) + { + ctx.LiftScope(); + Logic_CreateAndAssignToParentStart(ctx); + ctx.UnLiftScope(); + } + } + + public override void WriteGetObject() + { + ThrowIfDisposed(); + + // Deferring Checking + // + _deferringWriter.WriteGetObject(); + if (_deferringWriter.Handled) + { + return; + } + + // Error Checking + // + if (_nextNodeMustBeEndMember) + { + string err = SR.Get(SRID.ValueMustBeFollowedByEndMember); + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + XamlMember parentProperty = (_context.CurrentType == null && _context.Depth > 1) + ? _context.ParentProperty + : _context.CurrentProperty; // there is a push frame below making this the parent property. + if (parentProperty == null) + { + XamlType xamlType = (_context.CurrentType == null && _context.Depth > 1) + ? _context.ParentType + : _context.CurrentType; + + string err = (xamlType != null) + ? SR.Get(SRID.NoPropertyInCurrentFrame_GO, xamlType.ToString()) + : SR.Get(SRID.NoPropertyInCurrentFrame_GO_noType); + + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + + // Real processing begins here. + // + + //The first node (T, SO, or EP) after an EndObject should null out _lastInstance. + _lastInstance = null; + + // A Frame is pushed by either a AddNamespace or a WriteGet/StartObject + if (_context.CurrentType != null) + { + _context.PushScope(); + } + + TryCreateParentInstance(_context); + + _context.CurrentIsObjectFromMember = true; + + object parentInstance = _context.ParentInstance; + _context.CurrentType = parentProperty.Type; + + object inst = Runtime.GetValue(parentInstance, parentProperty); + if (inst == null) + { + throw _context.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.GetObjectNull, parentInstance.GetType(), parentProperty.Name))); + } + _context.CurrentInstance = inst; + if (parentProperty.Type.IsCollection || parentProperty.Type.IsDictionary) + { + _context.CurrentCollection = inst; + } + } + + public override void WriteStartObject(XamlType xamlType) + { + ThrowIfDisposed(); + if (xamlType == null) + { + throw new ArgumentNullException("xamlType"); + } + + // Deferring Checking + // + _deferringWriter.WriteStartObject(xamlType); + if (_deferringWriter.Handled) + { + return; + } + + // This is to store the correct start line number and position + // of start object as _context.LineNumber & Position might get updated + // to the next start object if the current object is created through StartMember function + _context.LineNumber_StartObject = _context.LineNumber; + _context.LinePosition_StartObject = _context.LinePosition; + + // Error Checking + // + if (_nextNodeMustBeEndMember) + { + string err = SR.Get(SRID.ValueMustBeFollowedByEndMember); + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + if (xamlType.IsUnknown) + { + string err = SR.Get(SRID.CantCreateUnknownType, xamlType.GetQualifiedName()); + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + + if (_context.CurrentType != null && _context.CurrentProperty == null) + { + string err = SR.Get(SRID.NoPropertyInCurrentFrame_SO, xamlType.ToString(), + _context.CurrentType.ToString()); + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + + // Real processing begins here. + // + + //The first node (T, SO, or EP) after an EndObject should null out _lastInstance. + _lastInstance = null; + + // A Frame is pushed by either a AddNamespace or a WriteGet/StartObject + if (_context.CurrentType != null) + { + _context.PushScope(); + } + + _context.CurrentType = xamlType; + + // Don't create the Root Instance if we were given one in the settings. + // This is an important senario when a XamlObject loads a XamlDefinition of itself + // in it's constructor. The instance is already created (that is how we got into + // the constructor), now don't create the first StartObject use the existing instance. + // + if ((_context.LiveDepth == 1) && (_rootObjectInstance != null)) + { + XamlType rootType = GetXamlType(_rootObjectInstance.GetType()); + if (!rootType.CanAssignTo(_context.CurrentType)) + { + throw new XamlParseException(SR.Get(SRID.CantAssignRootInstance, + rootType.GetQualifiedName(), xamlType.GetQualifiedName())); + } + _context.CurrentInstance = _rootObjectInstance; + if (_context.CurrentType.IsCollection || _context.CurrentType.IsDictionary) + { + _context.CurrentCollection = _rootObjectInstance; + } + Logic_BeginInit(_context); + } + + } + + public override void WriteEndObject() + { + ThrowIfDisposed(); + + // Deferring Checking + // + _deferringWriter.WriteEndObject(); + if (_deferringWriter.Handled) + { + if (_deferringWriter.Mode == DeferringMode.TemplateReady) + { + Debug.Assert(_context.CurrentProperty.DeferringLoader != null); + XamlNodeList templateList = _deferringWriter.CollectTemplateList(); + _context.PushScope(); + _context.CurrentInstance = (XamlReader)templateList.GetReader(); + } + return; + } + + // Error Checking + // + if (_nextNodeMustBeEndMember) + { + string err = SR.Get(SRID.ValueMustBeFollowedByEndMember); + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + if (_context.CurrentType == null) + { + string err = SR.Get(SRID.NoTypeInCurrentFrame_EO); + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + if (_context.CurrentProperty != null) + { + string err = SR.Get(SRID.OpenPropertyInCurrentFrame_EO, _context.CurrentType.ToString(), + _context.CurrentProperty.ToString()); + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + + // Real processing begins here. + // + Debug.Assert(_context.LiveDepth > 0); + bool hasUnresolvedChildren = HasUnresolvedChildren(_context.CurrentInstance); + bool isFixupToken = _context.CurrentInstance is NameFixupToken; + + if (!_context.CurrentIsObjectFromMember) + { + // We defer creation in WriteObject because we might have args for + // Create From InitText, or Create with parameters. + // But, If we got to End Object and still haven't Created it, + // then create it now. + if (_context.CurrentInstance == null) + { + Logic_CreateAndAssignToParentStart(_context); + } + + XamlType xamlType = _context.CurrentType; + object instance = _context.CurrentInstance; + OnAfterProperties(instance); + + if (_context.CurrentType.IsMarkupExtension) + { + // Can't call EndInit() or ProvideValue() if all the properties are not in. + if (hasUnresolvedChildren) + { + Logic_DeferProvideValue(_context); + } + else + { + ExecutePendingAdds(_context.CurrentType, _context.CurrentInstance); + Logic_EndInit(_context); + instance = _context.CurrentInstance; + Logic_AssignProvidedValue(_context); + if (_context.CurrentInstanceRegisteredName != null) + { + // Names on MEs apply to the ME, not to the provided value + if (_nameFixupGraph != null) + { + TriggerNameResolution(instance, _context.CurrentInstanceRegisteredName); + } + _context.CurrentInstanceRegisteredName = null; + } + instance = _context.CurrentInstance; + isFixupToken = instance is NameFixupToken; + hasUnresolvedChildren = !isFixupToken && HasUnresolvedChildren(instance); + } + } + else + { + if (_context.LiveDepth > 1) + { + if (!_context.CurrentWasAssignedAtCreation) + { + Logic_DoAssignmentToParentProperty(_context); + } + } + + // Can't call EndInit() on an object if any of its properties are not resolved. + // + if (hasUnresolvedChildren) + { + if (_context.LiveDepth > 1) + { + Logic_AddDependencyForUnresolvedChildren(_context, null); + } + } + else if (!isFixupToken) + { + ExecutePendingAdds(_context.CurrentType, _context.CurrentInstance); + Logic_EndInit(_context); + } + } + } + else // object is retrieved + { + if (hasUnresolvedChildren) + { + Debug.Assert(_context.LiveDepth > 1); + Logic_AddDependencyForUnresolvedChildren(_context, null); + } + else + { + ExecutePendingAdds(_context.CurrentType, _context.CurrentInstance); + } + + if (_context.ParentIsPropertyValueSet) + { + throw _context.WithLineInfo(new XamlDuplicateMemberException( + _context.ParentProperty, + _context.ParentType)); + } + } + _lastInstance = _context.CurrentInstance; + string name = _context.CurrentInstanceRegisteredName; + + if (_context.LiveDepth == 1) + { + _rootNamescope = _context.RootNameScope; + } + + // We must PopScope() before Forward Reference Resolution. Because + // References are only returned to "completed" object. Completed + // is determined in part by the object's absence from the builder stack. + _context.PopScope(); + + if (hasUnresolvedChildren) + { + _nameFixupGraph.IsOffTheStack(_lastInstance, name, _context.LineNumber, _context.LinePosition); + } + else if (isFixupToken) + { + if (name != null) + { + NameFixupToken token = (NameFixupToken)_lastInstance; + if (token.FixupType == FixupType.ObjectInitializationValue && !token.CanAssignDirectly) + { + // This is a TypeConverted object, but the converter returned a FixupToken. + // We need to put the name on the token's saved context, so that we can register + // the name to the actual object when we finally create it. + var objectFrame = (ObjectWriterFrame)token.SavedContext.Stack.PreviousFrame; + objectFrame.InstanceRegisteredName = name; + } + } + } + else if (_nameFixupGraph != null) + { + TriggerNameResolution(_lastInstance, name); + } + + if (_context.LiveDepth == 0 && !_inDispose) + { + CompleteNameReferences(); + _context.RaiseNameScopeInitializationCompleteEvent(); + } + } + + public override void WriteStartMember(XamlMember property) + { + ThrowIfDisposed(); + if (property == null) + { + throw new ArgumentNullException("property"); + } + + // Deferring Checking + // + _deferringWriter.WriteStartMember(property); + if (_deferringWriter.Handled) + { + return; + } + + // Error Checking + // + string err = null; + if (_nextNodeMustBeEndMember) + { + err = SR.Get(SRID.ValueMustBeFollowedByEndMember); + } + else if (property == XamlLanguage.UnknownContent) + { + err = SR.Get(SRID.TypeHasNoContentProperty, _context.CurrentType); + } + else if (property.IsUnknown) + { + err = SR.Get(SRID.CantSetUnknownProperty, property.ToString()); + } + else if (_context.CurrentProperty != null) + { + err = SR.Get(SRID.OpenPropertyInCurrentFrame_SM, _context.CurrentType.ToString(), + _context.CurrentProperty.ToString(), + property.ToString()); + } + else if (_context.CurrentType == null) + { + err = SR.Get(SRID.NoTypeInCurrentFrame_SM, property.ToString()); + } + + if (err != null) + { + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + + // Real processing starts here. + // + Debug.Assert(_context.LiveDepth > 0); + _context.CurrentProperty = property; + + // Duplicate Property Setting Check. + // + Logic_DuplicatePropertyCheck(_context, property, false /*onParent*/); + + // If we haven't created the object yet then consider creating it now. + // We need an object instance to set property values on. + if (_context.CurrentInstance == null) + { + if (!IsConstructionDirective(_context.CurrentProperty) + && !IsDirectiveAllowedOnNullInstance(_context.CurrentProperty, _context.CurrentType)) + { + Logic_CreateAndAssignToParentStart(_context); + } + + // Creates the backing collection for x:PositionParameters + // Note: this sets the "current collection" but the object instance is still NULL!! + if (property == XamlLanguage.PositionalParameters) + { + _context.CurrentCollection = new List(); + } + } + else // instance != null + { + // If we see any construction directives (like x:Arguments, x:Type) when we already have an instance, we throw + if (IsTextConstructionDirective(property)) + { + throw _context.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.LateConstructionDirective, property.Name))); + } + + if (_context.CurrentIsTypeConvertedObject) + { + // This is an error path where properties are set on a Type converter instance + // We allow directives or attachable properties but not "normal" properties. + if (!property.IsDirective && !property.IsAttachable) + { + throw _context.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.SettingPropertiesIsNotAllowed, property.Name))); + } + // We don't allow attachable properties either, if the the Type Converter returned + // a NameFixupToken. We could consider allowing this in the future by storing the + // APs on the token. + if (property.IsAttachable && _context.CurrentInstance is NameFixupToken) + { + NameFixupToken token = (NameFixupToken)_context.CurrentInstance; + throw _context.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.AttachedPropOnFwdRefTC, + property, _context.CurrentType, string.Join(", ", token.NeededNames.ToArray())))); + } + } + } + if (property.IsDirective && property != XamlLanguage.Items && property != XamlLanguage.PositionalParameters) + { + // Creates the container for x:Arguments (possible other future directives) If this was + // just for x:Arguments it could be moved into the (inst == null) case above. + // Note: this sets the "current collection" but does not touch the "current instance". + // Note: there is a special case for x:PosParam above because the collection type is not public. + // Note: The dictionary check is there because Collection and Dictionary checks go together. + XamlType propertyXamlType = property.Type; + if (propertyXamlType.IsCollection || propertyXamlType.IsDictionary) + { + _context.CurrentCollection = Runtime.CreateInstance(property.Type, null); + } + } + } + + public override void WriteEndMember() + { + ThrowIfDisposed(); + + // Deferring Checking + // + _deferringWriter.WriteEndMember(); + if (_deferringWriter.Handled) + { + return; + } + + // Error Checking + // + XamlMember property; + // In the Text value case we will be on the text frame + // and the property is in the parent. + if (_context.CurrentType == null) + { + property = _context.ParentProperty; + } + // In the Object value case we pop'ed and assigned the value already. + else + { + property = _context.CurrentProperty; + } + + if (property == null) + { + string err = (_context.CurrentType != null) + ? SR.Get(SRID.NoPropertyInCurrentFrame_EM, _context.CurrentType.ToString()) + : SR.Get(SRID.NoPropertyInCurrentFrame_EM_noType); + + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + + // Real processing starts here. + // + _nextNodeMustBeEndMember = false; + + //The first node (T, SO, or EP) after an EndObject should null out _lastInstance. + _lastInstance = null; + + if (property == XamlLanguage.Arguments) + { + _context.CurrentCtorArgs = ((List)_context.CurrentCollection).ToArray(); + } + else if (property == XamlLanguage.Initialization) + { + Logic_CreateFromInitializationValue(_context); + } + else if (property == XamlLanguage.Items) + { + _context.CurrentCollection = null; + } + else if (property == XamlLanguage.PositionalParameters) + { + Logic_ConvertPositionalParamsToArgs(_context); + } + else if (property == XamlLanguage.Class) + { + object value = null; + if (_context.CurrentType == null) + { + value = _context.CurrentInstance; + _context.PopScope(); + } + Logic_ValidateXClass(_context, value); + } + else if (_context.CurrentType == null) + { + // CurrentType == null means we are in a Value Frame (under a property) + // [rather than the result of some S0 sub-tree]. + // For example Red or results in: + // SM Color; V "Red"; EM; // and the type converter for Color will be invoked + // But: Red results in: + // SM Color; SO String; SM _init; V "Red"; EM; EO; EM + // Currently the String object is assigned into the Color Property in EndObject. + // Converting XML TEXT like "Red" is completly different than Red + // Conversion today will take more than TEXT as input. + // Template Conversion is also done here + // + object value = _context.CurrentInstance; + + bool shouldSetValue = true; + if (value != null) + { + MarkupExtension me = value as MarkupExtension; + if (me != null) + { + _context.CurrentInstance = me; + XamlType valueXamlType = GetXamlType(value.GetType()); + if (!property.Type.IsMarkupExtension || !valueXamlType.CanAssignTo(property.Type)) + { + Logic_AssignProvidedValue(_context); + shouldSetValue = false; + } + // If the MarkupExtension's provided value is not assigned to the property, the MarkupExtension will be assigned directly. + } + else // normal TC case. + { + // If the value is a string or is not directly assignable, convert it. + XamlType valueXamlType = GetXamlType(value.GetType()); + if (valueXamlType == XamlLanguage.String || !valueXamlType.CanAssignTo(property.Type)) + { + if (property.IsDirective && property == XamlLanguage.Key && !Logic_ShouldConvertKey(_context)) + { + shouldSetValue = true; + _context.ParentKeyIsUnconverted = true; + } + else + { + shouldSetValue = Logic_CreatePropertyValueFromValue(_context); + } + } + } + } + _lastInstance = _context.CurrentInstance; + if (shouldSetValue) + { + Logic_DoAssignmentToParentProperty(_context); + } + _context.PopScope(); // Value Node Scope + } + + // Clear Current Property because the value for this property + // has been set and the frame popped off. + _context.CurrentProperty = null; + _context.CurrentIsPropertyValueSet = false; + } + + public override void WriteValue(object value) + { + ThrowIfDisposed(); + + // Deferring Checking + // + _deferringWriter.WriteValue(value); + if (_deferringWriter.Handled) + { + // Handles the case of SM Template; V NodeList; EM + if (_deferringWriter.Mode == DeferringMode.TemplateReady) + { + Debug.Assert(_context.CurrentProperty.DeferringLoader != null); + XamlNodeList templateList = _deferringWriter.CollectTemplateList(); + _context.PushScope(); + _context.CurrentInstance = (XamlReader)templateList.GetReader(); + } + return; + } + + // Error Checking + // + XamlMember currentProperty = _context.CurrentProperty; + if (currentProperty == null) + { + string err = (_context.CurrentType != null) + ? SR.Get(SRID.NoPropertyInCurrentFrame_V, value, _context.CurrentType.ToString()) + : SR.Get(SRID.NoPropertyInCurrentFrame_V_noType, value); + + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + + //The first node (T, SO, or EP) after an EndObject should null out _lastInstance. + _lastInstance = null; + + _context.PushScope(); + _context.CurrentInstance = value; + + // current property is now parentproperty. (pushScope above) + // Name change to reduce confusion. + XamlMember parentProperty = currentProperty; + currentProperty = null; + + // There are two cases. + // 1) Text on a regular property. + // Processed on EndMember. (not here) + // 2) Text on a directive with a list type. + // Processed Item by item right here. + _nextNodeMustBeEndMember = true; + if (parentProperty.IsDirective) + { + XamlType parentXamlType = parentProperty.Type; + if (parentXamlType.IsCollection || parentXamlType.IsDictionary) + { + _nextNodeMustBeEndMember = false; + if (parentProperty == XamlLanguage.PositionalParameters) + { + _context.CurrentType = XamlLanguage.PositionalParameterDescriptor; + _context.CurrentInstance = new PositionalParameterDescriptor(value, true); + Logic_DoAssignmentToParentCollection(_context); + _context.PopScope(); + } + else + { + _context.CurrentInstance = value; + Logic_DoAssignmentToParentCollection(_context); + _context.PopScope(); + } + } + } + } + + public override void WriteNamespace(NamespaceDeclaration namespaceDeclaration) + { + ThrowIfDisposed(); + if (namespaceDeclaration == null) + { + throw new ArgumentNullException("namespaceDeclaration"); + } + if(namespaceDeclaration.Prefix == null) + { + throw new ArgumentException(SR.Get(SRID.NamespaceDeclarationPrefixCannotBeNull)); + } + if(namespaceDeclaration.Namespace == null) + { + throw new ArgumentException(SR.Get(SRID.NamespaceDeclarationNamespaceCannotBeNull)); + } + + // Deferring Checking + // + _deferringWriter.WriteNamespace(namespaceDeclaration); + if (_deferringWriter.Handled) + { + return; + } + + // Error Checking + // + if (_nextNodeMustBeEndMember) + { + string err = SR.Get(SRID.ValueMustBeFollowedByEndMember); + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + if (_context.CurrentType != null && _context.CurrentProperty == null) + { + string err = SR.Get(SRID.NoPropertyInCurrentFrame_NS, namespaceDeclaration.Prefix, + namespaceDeclaration.Namespace, + _context.CurrentType.ToString()); + throw _context.WithLineInfo(new XamlObjectWriterException(err)); + } + + // A Frame is pushed by either a AddNamespace or a WriteObject + if (_context.CurrentType != null) + { + _context.PushScope(); + } + _context.AddNamespacePrefix(namespaceDeclaration.Prefix, namespaceDeclaration.Namespace); + } + + public void Clear() + { + ThrowIfDisposed(); + while (_context.LiveDepth > 0) + { + _context.PopScope(); + } + _rootNamescope = null; + _nextNodeMustBeEndMember = false; + _deferringWriter.Clear(); + _context.PushScope(); + } + + protected override void Dispose(bool disposing) + { + try + { + _inDispose = true; + if (disposing && !IsDisposed) + { + bool seenStartObject = _context.LiveDepth > 1 || _context.CurrentType != null; + if (seenStartObject) + { + while (_context.LiveDepth > 0) + { + if (_context.CurrentProperty != null) + { + WriteEndMember(); + } + WriteEndObject(); + } + } + _deferringWriter.Close(); + _deferringWriter = null; + + // null references to external objects that might be + // held alive if this object is not released by its + // caller after the Dispose call. + _context = null; + _afterBeginInitHandler = null; + _beforePropertiesHandler = null; + _afterPropertiesHandler = null; + _afterEndInitHandler = null; + } + } + finally + { + base.Dispose(disposing); + _inDispose = false; + } + } + + private void ThrowIfDisposed() + { + if(IsDisposed) + { + throw new ObjectDisposedException("XamlObjectWriter"); + } + } + + public INameScope RootNameScope + { + get + { + if (_rootNamescope != null) + { + return _rootNamescope; + } + else + { + return _context.RootNameScope; + } + } + } + + //Result should return the _lastInstance when called after an EO. Otherwise, it should return null. + //Currently we null out _lastInstance in the nodes that can come after EO (T, SO, EP). Can an NS come, + // what should we do? + public virtual object Result + { + get + { + return _lastInstance; + } + } + + public override XamlSchemaContext SchemaContext + { + get + { + ThrowIfDisposed(); + return _context.SchemaContext; + } + } + + #region IXamlLineInfoConsumer Members + + public void SetLineInfo(int lineNumber, int linePosition) + { + ThrowIfDisposed(); + _context.LineNumber = lineNumber; + _context.LinePosition = linePosition; + + // Deferring Checking + // + _deferringWriter.SetLineInfo(lineNumber, linePosition); + } + + public bool ShouldProvideLineInfo + { + get + { + ThrowIfDisposed(); + return true; + } + } + + #endregion + + // ---------------- Private Exception / Line Number ------ + + XamlException IAddLineInfo.WithLineInfo(XamlException ex) + { + return _context.WithLineInfo(ex); + } + + // ----------------- Private methods ------------------- + + /// + /// Gets the Key alias property when x:Key is not present. + /// + private object GetKeyFromInstance(object instance, XamlType instanceType, IAddLineInfo lineInfo) + { + XamlMember keyProperty = instanceType.GetAliasedProperty(XamlLanguage.Key); + if (keyProperty == null || instance == null) + { + throw lineInfo.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.MissingKey, instanceType.Name))); + } + object key = Runtime.GetValue(instance, keyProperty); + return key; + } + + private XamlType GetXamlType(Type clrType) + { + XamlType result = SchemaContext.GetXamlType(clrType); + if (result == null) + { + throw new InvalidOperationException(SR.Get(SRID.ObjectWriterTypeNotAllowed, + SchemaContext.GetType(), clrType)); + } + return result; + } + + // These are the all the directives that affect Construction of object. + bool IsConstructionDirective(XamlMember xamlMember) + { + return xamlMember == XamlLanguage.Arguments + || xamlMember == XamlLanguage.Base + || xamlMember == XamlLanguage.FactoryMethod + || xamlMember == XamlLanguage.Initialization + || xamlMember == XamlLanguage.PositionalParameters + || xamlMember == XamlLanguage.TypeArguments; + } + + // BAML sometimes sends the x:base directive later than it should + // so these are the Ctor Directives we worry about 'Users' messing up. + bool IsTextConstructionDirective(XamlMember xamlMember) + { + return xamlMember == XamlLanguage.Arguments + || xamlMember == XamlLanguage.FactoryMethod + || xamlMember == XamlLanguage.PositionalParameters + || xamlMember == XamlLanguage.TypeArguments; + } + + // Non Ctor directives that are also allowed before object creation. + // These are compat issues with BAML recording x:Key x:Uid earlier than + // it current XAML standards. + bool IsDirectiveAllowedOnNullInstance(XamlMember xamlMember, XamlType xamlType) + { + if (xamlMember == XamlLanguage.Key) + { + return true; + } + if (xamlMember == XamlLanguage.Uid) + { + if (null == xamlType.GetAliasedProperty(XamlLanguage.Uid)) + { + return true; + } + } + return false; + } + + private void Logic_CreateAndAssignToParentStart(ObjectWriterContext ctx) + { + object inst; + object factoryMethodName; + XamlType currentType = ctx.CurrentType; + + if (ctx.CurrentIsObjectFromMember) + { + throw ctx.WithLineInfo(new XamlInternalException(SR.Get(SRID.ConstructImplicitType))); + } + + // If the Constructor Arguments came from ME {} syntax and there are + // any MEs on the parameter list, they will be un-evaluated because + // of the rule in AssignProvideValue that skips PV() if the + // parent instance is null (which is always is for Ctor params). + // So Unpack and call Provide Value on items in the arguement vector here. + if (currentType.IsMarkupExtension && ctx.CurrentCtorArgs != null) + { + object[] args = ctx.CurrentCtorArgs; + for (int i = 0; i < args.Length; i++) + { + MarkupExtension me = args[i] as MarkupExtension; + if (me != null) + { + args[i] = Logic_PushAndPopAProvideValueStackFrame(ctx, XamlLanguage.PositionalParameters, me, false); + } + } + } + + // If No Factory Method + if (!ctx.CurrentHasPreconstructionPropertyValuesDictionary || + !ctx.CurrentPreconstructionPropertyValues.TryGetValue(XamlLanguage.FactoryMethod, out factoryMethodName)) + { + inst = Runtime.CreateInstance(currentType, ctx.CurrentCtorArgs); + } + else // with Factory Method + { + XamlPropertyName propertyName = XamlPropertyName.Parse((string)factoryMethodName); + if (propertyName == null) + { + string errMsg = string.Format(TypeConverterHelper.InvariantEnglishUS, SR.Get(SRID.InvalidExpression), factoryMethodName); + throw ctx.WithLineInfo(new XamlInternalException(errMsg)); + } + + XamlType ownerType; + if (propertyName.Owner == null) + { + ownerType = currentType; + } + else + { + ownerType = ctx.GetXamlType(propertyName.Owner); + if (ownerType == null) + { + XamlTypeName ownerTypeName = ctx.GetXamlTypeName(propertyName.Owner); + throw ctx.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.CannotResolveTypeForFactoryMethod, ownerTypeName, propertyName.Name))); + } + } + + inst = Runtime.CreateWithFactoryMethod(ownerType, propertyName.Name, ctx.CurrentCtorArgs); + + Debug.Assert(inst != null); // runtime throws before it returns null. + + XamlType instType = GetXamlType(inst.GetType()); + if (!instType.CanAssignTo(currentType)) + { + throw ctx.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.NotAssignableFrom, currentType.GetQualifiedName(), instType.GetQualifiedName()))); + } + } + ctx.CurrentCtorArgs = null; + ctx.CurrentInstance = inst; + if (currentType.IsCollection || currentType.IsDictionary) + { + ctx.CurrentCollection = inst; + } + + Logic_BeginInit(ctx); + + // If UsableDuringInit, Assign to parent + // We don't want to assign MEs to the parent since we need to call ProvideValue on them + // which is handled in WriteEndObject + if (ctx.LiveDepth > 1 && !(inst is MarkupExtension)) + { + if (ctx.LiveDepth > 1) + { + Logic_CheckAssignmentToParentStart(ctx); + } + } + + OnBeforeProperties(inst); + + Logic_ApplyCurrentPreconstructionPropertyValues(ctx); + } + + private void Logic_ConvertPositionalParamsToArgs(ObjectWriterContext ctx) + { + XamlType meType = ctx.CurrentType; + if (!meType.IsMarkupExtension) + { + throw ctx.WithLineInfo(new XamlInternalException(SR.Get(SRID.NonMEWithPositionalParameters))); + } + + var rawArgs = (List)ctx.CurrentCollection; + object[] argInstances = new object[rawArgs.Count]; + IEnumerable paramTypes = meType.GetPositionalParameters(rawArgs.Count); + + if (null == paramTypes) + { + // A constructor with the specified number of arguments doesn't exist + string msg = string.Format(TypeConverterHelper.InvariantEnglishUS, SR.Get(SRID.NoSuchConstructor), rawArgs.Count, meType.Name); + throw ctx.WithLineInfo(new XamlObjectWriterException(msg)); + } + + int i = 0; + foreach (XamlType pparamType in paramTypes) + { + if (i < rawArgs.Count) + { + object inst; + PositionalParameterDescriptor pparam = rawArgs[i]; + if (pparam.WasText) + { + XamlValueConverter ts = pparamType.TypeConverter; + object value = pparam.Value; + inst = Logic_CreateFromValue(ctx, ts, value, null, pparamType.Name); + } + else + { + inst = rawArgs[i].Value; + } + argInstances[i++] = inst; + } + else + { + throw ctx.WithLineInfo(new XamlInternalException(SR.Get(SRID.PositionalParamsWrongLength))); + } + ctx.CurrentCtorArgs = argInstances; + } + } + + private void Logic_CreateFromInitializationValue(ObjectWriterContext ctx) + { + XamlType xamlType = ctx.ParentType; + XamlValueConverter ts = xamlType.TypeConverter; + object value = ctx.CurrentInstance; + object inst = null; + + if (xamlType.IsUnknown) + { + string err = SR.Get(SRID.CantCreateUnknownType, xamlType.GetQualifiedName()); + throw ctx.WithLineInfo(new XamlObjectWriterException(err)); + } + if (ts == null) + { + throw ctx.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.InitializationSyntaxWithoutTypeConverter, xamlType.GetQualifiedName()))); + } + inst = Logic_CreateFromValue(ctx, ts, value, null, xamlType.Name); + + // Pop off the Text Frame. + ctx.PopScope(); + + ctx.CurrentInstance = inst; + ctx.CurrentIsTypeConvertedObject = true; + + if (!(inst is NameFixupToken)) + { + if (xamlType.IsCollection || xamlType.IsDictionary) + { + ctx.CurrentCollection = inst; + } + Logic_ApplyCurrentPreconstructionPropertyValues(ctx, true); + } + } + + private object Logic_CreateFromValue(ObjectWriterContext ctx, XamlValueConverter typeConverter, + object value, XamlMember property, string targetName) + { + return Logic_CreateFromValue(ctx, typeConverter, value, property, targetName, this); + } + + private object Logic_CreateFromValue(ObjectWriterContext ctx, XamlValueConverter typeConverter, + object value, XamlMember property, string targetName, IAddLineInfo lineInfo) + { + try + { + object result = Runtime.CreateFromValue(ctx.ServiceProviderContext, typeConverter, + value, property); + return result; + } + catch (Exception ex) + { + if (CriticalExceptions.IsCriticalException(ex)) + { + throw; + } + string err = SR.Get(SRID.TypeConverterFailed, targetName, value); + throw lineInfo.WithLineInfo(new XamlObjectWriterException(err, ex)); + } + } + + private bool Logic_CreatePropertyValueFromValue(ObjectWriterContext ctx) + { + XamlMember property = ctx.ParentProperty; + XamlType propertyType = property.Type; + + object value = ctx.CurrentInstance; + XamlReader deferredContent = value as XamlReader; + if (deferredContent != null) + { + // property.DeferringLoader looks at the property AND the type of the property. + XamlValueConverter deferringLoader = property.DeferringLoader; + if (deferringLoader != null) + { + ctx.CurrentInstance = Runtime.DeferredLoad( + ctx.ServiceProviderContext, deferringLoader, deferredContent); + return true; + } + } + + // property.TypeConverter looks at the property AND the type of the property. + XamlValueConverter converter = property.TypeConverter; + object inst = null; + +#if !TARGETTING35SP1 + XamlType declaringType = null; + if (property.IsAttachable) + { + declaringType = property.DeclaringType; + } + else + { + declaringType = ctx.ParentType; + } + + if (property != null && !property.IsUnknown && declaringType != null) + { + XamlType grandParentXamlType = ctx.GrandParentType; + if (property.IsDirective && + property == XamlLanguage.Key && + grandParentXamlType != null && + grandParentXamlType.IsDictionary) + { + converter = grandParentXamlType.KeyType.TypeConverter; + } + if (converter!= null && converter.ConverterType != null && converter != BuiltInValueConverter.String) + { + TypeConverter typeConverter = Runtime.GetConverterInstance(converter); + if (typeConverter != null) + { + if (declaringType.SetTypeConverterHandler != null) + { + var eventArgs = new XamlSetTypeConverterEventArgs(property, typeConverter, value, ctx.ServiceProviderContext, + TypeConverterHelper.InvariantEnglishUS, + ctx.ParentInstance); + + eventArgs.CurrentType = declaringType; + + declaringType.SetTypeConverterHandler(ctx.ParentInstance, eventArgs); + if (eventArgs.Handled == true) + { + return false; + } + } + } + } + } +#endif + + if (converter != null) + { + inst = Logic_CreateFromValue(ctx, converter, value, property, property.Name); + } + else + { + // the value may be assignable as the property value directly, + // so pass it through to be set to the property value later. + inst = value; + } + ctx.CurrentInstance = inst; + return true; + } + + // For backcompat with 3.x parser, if the compat flag PreferUnconvertedKeys is set, + // we don't convert keys if the dictionary implements non-generic IDictionary, unless: + // - we've already failed calling IDictionary.Add on this same instance, or + // - it's a built-in BCL dictionary that we know requires conversion. + // + // We track this state via the following flags: + // - KeyIsUnconverted on a dictionary item frame indicates that the key was not converted. + // - ShouldConvertChildKeys on a dictionary frame indicates that the dictionary requires + // key conversion. + // - ShouldNotConvertChildKeys on a dictionary frame indicates that the add of the first + // key succeeded without conversion, so we shouldn't convert any of the remaining keys. + // If neither of the Should flags is set, that means this is the first dictionary item, + // so we'll try without converting the key, and fall back to conversion if it fails. + private bool Logic_ShouldConvertKey(ObjectWriterContext ctx) + { + Debug.Assert(ctx.ParentProperty == XamlLanguage.Key); + if (!_preferUnconvertedDictionaryKeys || ctx.GrandParentShouldConvertChildKeys) + { + return true; + } + if (ctx.GrandParentShouldNotConvertChildKeys) + { + return false; + } + XamlType dictionaryType = ctx.GrandParentType; + if (dictionaryType != null && dictionaryType.IsDictionary && + typeof(System.Collections.IDictionary).IsAssignableFrom(dictionaryType.UnderlyingType) && + !IsBuiltInGenericDictionary(dictionaryType.UnderlyingType)) + { + return false; + } + ctx.GrandParentShouldConvertChildKeys = true; + return true; + } + + private static bool IsBuiltInGenericDictionary(Type type) + { + if (type == null || !type.IsGenericType) + { + return false; + } + Type openGeneric = type.GetGenericTypeDefinition(); + return openGeneric == typeof(Dictionary<,>) || + openGeneric == typeof(SortedDictionary<,>) || + openGeneric == typeof(SortedList<,>) || + openGeneric == typeof(ConcurrentDictionary<,>); + } + + private void Logic_BeginInit(ObjectWriterContext ctx) + { + object inst = ctx.CurrentInstance; + XamlType xamlType = ctx.CurrentType; + + Runtime.InitializationGuard(xamlType, inst, true); + if (ctx.BaseUri != null) + { + Runtime.SetUriBase(xamlType, inst, ctx.BaseUri); + } + + // This is back compat with WPF 3.5. + // This activates a second path to setting the object's + // _contentLoaded in the generated code. + if (inst == ctx.RootInstance) + { + Logic_SetConnectionId(ctx, 0, inst); + } + + OnAfterBeginInit(inst); + } + + private void Logic_EndInit(ObjectWriterContext ctx) + { + XamlType xamlType = ctx.CurrentType; + object inst = ctx.CurrentInstance; + + Runtime.InitializationGuard(xamlType, inst, false); + + OnAfterEndInit(inst); + } + + // Called when a MarkupExtension has unresolved children and so we can't call ProvideValue on it + private void Logic_DeferProvideValue(ObjectWriterContext ctx) + { + var deferredMarkupExtensionContext = ctx.GetSavedContext(SavedContextType.ReparseMarkupExtension); + if (ctx.LiveDepth > 2 && ctx.ParentProperty == XamlLanguage.Key && + ctx.GrandParentType.IsDictionary) + { + NameFixupToken token = GetTokenForUnresolvedChildren(ctx.CurrentInstance, + XamlLanguage.Key, deferredMarkupExtensionContext); + Logic_PendKeyFixupToken(ctx, token); + } + else + { + Logic_AddDependencyForUnresolvedChildren(ctx, deferredMarkupExtensionContext); + } + } + + private void Logic_DuplicatePropertyCheck(ObjectWriterContext ctx, XamlMember property, bool onParent) + { + if (!_skipDuplicatePropertyCheck) + { + HashSet setProperties = onParent ? ctx.ParentAssignedProperties : ctx.CurrentAssignedProperties; + if (setProperties.Contains(property)) + { + // In some cases, the XamlXmlWriter emits duplicate xml:space. We can ignore these + // since ObjectWriter doesn't actually process xml:space. + if (property != XamlLanguage.Space) + { + XamlType xamlType = onParent ? ctx.ParentType : ctx.CurrentType; + throw ctx.WithLineInfo(new XamlDuplicateMemberException(property, xamlType)); + } + } + else + { + setProperties.Add(property); + } + } + } + + private void Logic_ApplyCurrentPreconstructionPropertyValues(ObjectWriterContext ctx) + { + Logic_ApplyCurrentPreconstructionPropertyValues(ctx, false); + } + + private void Logic_ApplyCurrentPreconstructionPropertyValues(ObjectWriterContext ctx, bool skipDirectives) + { + if (ctx.CurrentHasPreconstructionPropertyValuesDictionary) + { + Dictionary propertyValues = ctx.CurrentPreconstructionPropertyValues; + + object value = null; + foreach (XamlMember prop in propertyValues.Keys) + { + if (skipDirectives && prop.IsDirective) + { + continue; + } + + value = propertyValues[prop]; + + // If the saved pre-construction property value is an ME + // then we need to evaluate it now. This in somewhat involved. + // We need to create a stack state that IProvideValueTarget and IRecieveMarkupExtension + // will understand. + // We did evaluate MEs on directives when the prop/value was saved, + // so don't call ProvideValue() now on directives here. + // (x:Key and x:Name need their own "saved spot" outside of PreconstructionPropertyValues) + + MarkupExtension me = value as MarkupExtension; + if (me != null && !prop.IsDirective) + { + Logic_PushAndPopAProvideValueStackFrame(ctx, prop, me, true); + } + else + { + Logic_ApplyPropertyValue(ctx, prop, value, false /*onParent*/); + } + } + } + } + + private object Logic_PushAndPopAProvideValueStackFrame(ObjectWriterContext ctx, XamlMember prop, MarkupExtension me, bool useIRME) + { + XamlMember savedProp = ctx.CurrentProperty; + ctx.CurrentProperty = prop; + + ctx.PushScope(); + ctx.CurrentInstance = me; + + object retVal = null; + if (useIRME) + { + Logic_AssignProvidedValue(ctx); + // retVal = null; + } + else + { + retVal = Runtime.CallProvideValue(me, ctx.ServiceProviderContext); + } + + ctx.PopScope(); + ctx.CurrentProperty = savedProp; + return retVal; + } + + private void Logic_ApplyPropertyValue(ObjectWriterContext ctx, XamlMember prop, + object value, bool onParent) + { + object inst = onParent ? ctx.ParentInstance : ctx.CurrentInstance; + if (value is XData) + { + XData xData = value as XData; + if (prop.Type.IsXData) + { + Runtime.SetXmlInstance(inst, prop, xData); + return; + } + else + { + value = xData.Text; + } + } + + SetValue(inst, prop, value); + + if (prop.IsDirective) + { + XamlType xamlType = onParent ? ctx.ParentType : ctx.CurrentType; + XamlMember propertyForDirective = xamlType.GetAliasedProperty(prop as XamlDirective); + if (prop != XamlLanguage.Key && propertyForDirective != null) + { + // handle aliases for x:Uid x:Lang etc. + Logic_DuplicatePropertyCheck(ctx, propertyForDirective, onParent); + object convertedValue = Logic_CreateFromValue(ctx, propertyForDirective.TypeConverter, value, propertyForDirective, propertyForDirective.Name); + SetValue(inst, propertyForDirective, convertedValue); + } + + if (prop == XamlLanguage.Name) + { + // register a named object + if (inst == ctx.CurrentInstance) + { + Logic_RegisterName_OnCurrent(ctx, (string)value); + } + else + { + Debug.Assert(inst == ctx.ParentInstance); + Logic_RegisterName_OnParent(ctx, (string)value); + } + } + else if (prop == XamlLanguage.ConnectionId) + { + Logic_SetConnectionId(ctx, (int)value, inst); + } + else if (prop == XamlLanguage.Base) + { + Logic_CheckBaseUri(ctx, (string)value); + ctx.BaseUri = new Uri((string)value); + if (ctx.ParentInstance != null) + { + Runtime.SetUriBase(ctx.ParentType, ctx.ParentInstance, ctx.BaseUri); + } + } + } + } + + private void Logic_CheckBaseUri(ObjectWriterContext ctx, string value) + { + // Make sure BaseUri is not already set and that we can only set BaseUri on the root element + // Depth > 2 because on the root element, SO/SM takes 1 slot, V is slot 2 + if ((ctx.BaseUri != null) || (ctx.Depth > 2)) + { + throw new XamlObjectWriterException(SR.Get(SRID.CannotSetBaseUri)); + } + } + + /// + /// Process the call to a MarkupExtension.ProvideValue() and assign the result + /// + private void Logic_AssignProvidedValue(ObjectWriterContext ctx) + { + bool handled = Logic_ProvideValue(ctx); + if (!handled && ctx.ParentProperty != null) + { + Logic_DoAssignmentToParentProperty(ctx); + } + } + + // Returns true if the assignment was handled by a SetMarkupExtensionHandler + private bool Logic_ProvideValue(ObjectWriterContext ctx) + { + object inst = ctx.CurrentInstance; + MarkupExtension me = (MarkupExtension)inst; + object parentInstance = ctx.ParentInstance; + XamlMember parentProperty = ctx.ParentProperty; + +#if !TARGETTING35SP1 + if (parentProperty != null && parentProperty.IsUnknown == false) + { + XamlType declaringType = null; + + if (parentProperty.IsAttachable) + { + declaringType = parentProperty.DeclaringType; + } + else + { + declaringType = ctx.ParentType; + } + + if (declaringType != null) + { + if (declaringType.SetMarkupExtensionHandler != null) + { + var eventArgs = new XamlSetMarkupExtensionEventArgs(parentProperty, me, ctx.ServiceProviderContext, parentInstance); + eventArgs.CurrentType = declaringType; + declaringType.SetMarkupExtensionHandler(parentInstance, eventArgs); + if (eventArgs.Handled == true) + { + return true; + } + } + } + } +#endif + // The Service Provider Interface IProvideValueTarget requires that we can supply ProvideValue with the + // instance of the left-hand side of the property assignment. Markup extensions that are assigned to + // directives are allowed to have a null left-hand instance. + + // For a MarkupExtension (ME), either the parent instance is not null, the parent property is a directive, + // or it is the live root instance. ME.ProvideValue must be invoked in each case, except where a ME is the + // live root instance and _skipProvideValueOnRoot is true. This allows live root instances of templates to + // remain as MEs where necessary. + Debug.Assert(parentInstance != null || parentProperty != null && parentProperty.IsDirective || ctx.LiveDepth == 1); + object value = me; + if (ctx.LiveDepth != 1 || !_skipProvideValueOnRoot) + { + value = Runtime.CallProvideValue(me, ctx.ServiceProviderContext); + } + + // Checking that the ME isn't the Root of the XAML Document. + if (ctx.ParentProperty != null) + { + if (value != null) + { + if (!(value is NameFixupToken)) + { + ctx.CurrentType = GetXamlType(value.GetType()); + } + } + else if (ctx.ParentProperty == XamlLanguage.Items) + { + ctx.CurrentType = ctx.ParentType.ItemType; + } + else + { + ctx.CurrentType = ctx.ParentProperty.Type; + } + ctx.CurrentInstance = value; + } + else + { + ctx.CurrentInstance = value; + } + return false; + } + + private void Logic_PendCurrentFixupToken_SetValue(ObjectWriterContext ctx, NameFixupToken token) + { + token.LineNumber = ctx.LineNumber; + token.LinePosition = ctx.LinePosition; + token.Runtime = Runtime; + NameFixupGraph.AddDependency(token); + } + + private void Logic_CheckAssignmentToParentStart(ObjectWriterContext ctx) + { + Debug.Assert(ctx.LiveDepth > 1); + + // First defeat the TopDown'ness if we are in a dictionary + // because the key property can come later, we must wait + // until End Object to compute the key for the Dictionary.Add(Key, val) + bool inDictionary = ((ctx.ParentProperty == XamlLanguage.Items) && ctx.ParentType.IsDictionary); + XamlType type = ctx.CurrentType; + + if (type.IsUsableDuringInitialization && !inDictionary) + { + ctx.CurrentWasAssignedAtCreation = true; + Logic_DoAssignmentToParentProperty(ctx); + } + else + { + ctx.CurrentWasAssignedAtCreation = false; + } + } + + private void Logic_DoAssignmentToParentCollection(ObjectWriterContext ctx) + { + object parentCollection = ctx.ParentCollection; + XamlType collectionType = ctx.ParentType; + XamlType currentType = ctx.CurrentType; + object value = ctx.CurrentInstance; + + if (!collectionType.IsDictionary) + { + if (!Logic_PendAssignmentToParentCollection(ctx, null, false)) + { + // If Value is a Markup Extention then check the collection item type + // if it can hold the ME then don't call ProvideValue(). + MarkupExtension me = value as MarkupExtension; + if(me != null && !Logic_WillParentCollectionAdd(ctx, value.GetType(), true)) + { + // We don't need to call Logic_ProvideValue() with the extra handler + // interfaces, because this is collection not a scalar property. + value = Runtime.CallProvideValue(me, ctx.ServiceProviderContext); + } + Runtime.Add(parentCollection, collectionType, value, currentType); + } + } + else + { + if (currentType == null) + { + currentType = value == null ? collectionType.ItemType : GetXamlType(value.GetType()); + } + object key = ctx.CurrentKey; + bool keyIsSet = ctx.CurrentIsKeySet; + if (!Logic_PendAssignmentToParentCollection(ctx, key, keyIsSet)) + { + if (!keyIsSet) + { + key = GetKeyFromInstance(value, currentType, this); + } + Logic_AddToParentDictionary(ctx, key, value); + } + } + } + + /// + /// Returns true when the item type of the collection is assignable from + /// the given type. Normally we wouldn't call this (Let the CLR check and + /// throw if the item doesn't fit) but for Markup Extensions we check this + /// Before calling ProvideValue(); + /// + /// The context + /// The type of the new item + /// return false if collection Item Type is Object + /// + private bool Logic_WillParentCollectionAdd(ObjectWriterContext ctx, Type type, bool excludeObjectType) + { + Debug.Assert(ctx.ParentType.IsCollection, "Logic_WillParentCollectionAdd called on a non-collection"); + + // The Parent Property is x:Items which is always List + // To get the real item type we need to go to the Type. + XamlType itemType = ctx.ParentType.ItemType; + + if (excludeObjectType && itemType == XamlLanguage.Object) + { + return false; + } + + if (itemType.UnderlyingType.IsAssignableFrom(type)) + { + return true; + } + return false; + } + + private void Logic_AddToParentDictionary(ObjectWriterContext ctx, object key, object value) + { + if (ctx.CurrentKeyIsUnconverted && !ctx.ParentShouldNotConvertChildKeys) + { + if (!ctx.ParentShouldConvertChildKeys) + { + // If we didn't convert the key earlier (see Logic_ShouldConvertKey for details), + // we try to add unconverted key, and if it fails, we convert it, and try again. + try + { + Runtime.AddToDictionary(ctx.ParentCollection, ctx.ParentType, value, ctx.CurrentType, key); + // We've succesfully added the key without converting it; we should apply the same + // policy to the other keys for this dictionary instance. + ctx.ParentShouldNotConvertChildKeys = true; + return; + } + catch (XamlObjectWriterException ex) + { + // A dictionary that is passed in the wrong key type should throw ArgumentException. + // However a naive implementer might throw InvalidCastException instead, so + // catch that too. + if (!(ex.InnerException is ArgumentException) && + !(ex.InnerException is InvalidCastException)) + { + throw; + } + if (Debugger.IsLogging()) + { + Debug.WriteLine(SR.Get(SRID.DictionaryFirstChanceException, ctx.ParentType, key, ctx.ParentType.KeyType)); + } + } + + // Adding an unconverted key failed, we should make sure that we convert all future + // keys on this dictionary instance. + ctx.ParentShouldConvertChildKeys = true; + } + // Else, this is a deferred add, where the uncoverted key was saved earlier, + // before the parent's ShouldConvertChildKeys flag was set. So we skip the + // Add up above, and go directly to the conversion below. + + // Reproduce the stack as it would have been at the point when the key was originally + // read, and run the type converter now. + Debug.Assert(ctx.CurrentProperty == null); + ctx.CurrentProperty = XamlLanguage.Key; + ctx.PushScope(); + ctx.CurrentInstance = key; + Logic_CreatePropertyValueFromValue(ctx); + key = ctx.CurrentInstance; + ctx.PopScope(); + ctx.CurrentProperty = null; + } + + Runtime.AddToDictionary(ctx.ParentCollection, ctx.ParentType, value, ctx.CurrentType, key); + } + + // If any adds to the current collection are pending forward-reference resolution, + // we need to queue up all the subsequent adds, so that the reference is added in order. + // Returns TRUE if the item was pended; FALSE if it should be added directly. + // Consider perf optimization to avoid a global lookup on every item + private bool Logic_PendAssignmentToParentCollection(ObjectWriterContext ctx, object key, bool keyIsSet) + { + object parentCollection = ctx.ParentCollection; + object value = ctx.CurrentInstance; + NameFixupToken keyToken = key as NameFixupToken; + NameFixupToken valueToken = value as NameFixupToken; + + List pendingCollection = null; + if (_pendingCollectionAdds != null) + { + PendingCollectionAdds.TryGetValue(parentCollection, out pendingCollection); + } + if (pendingCollection == null && + (keyToken != null || valueToken != null || + HasUnresolvedChildren(key) || HasUnresolvedChildren(value))) + { + // We pend the add not only if the key or value are unresolved, but also if they + // have any unresolved children. This avoids problems with unresolved implicit keys, + // the key's hashcode changing as its properties resolve, or incomplete data being + // passed into an Add method that does validation. + pendingCollection = new List(); + PendingCollectionAdds.Add(parentCollection, pendingCollection); + } + if (keyToken != null) + { + // Set KeyHolder to null since the item is no longer on the stack, + // so we won't be getting its key from the saved KeyHolder anymore + keyToken.Target.KeyHolder = null; + keyToken.Target.TemporaryCollectionIndex = pendingCollection.Count; + } + if (valueToken != null) + { + Logic_PendCurrentFixupToken_SetValue(ctx, valueToken); + valueToken.Target.TemporaryCollectionIndex = pendingCollection.Count; + } + if (pendingCollection != null) + { + PendingCollectionAdd pendingAdd = new PendingCollectionAdd + { + Key = key, + KeyIsSet = keyIsSet, + KeyIsUnconverted = ctx.CurrentKeyIsUnconverted, + Item = value, + ItemType = ctx.CurrentType, + LineNumber = ctx.LineNumber, + LinePosition = ctx.LinePosition + }; + pendingCollection.Add(pendingAdd); + if (pendingAdd.KeyIsUnconverted) + { + if (!PendingKeyConversionContexts.ContainsKey(parentCollection)) + { + // Snap a SavedContext so we can convert the key later, if needed + XamlSavedContext savedContext = ctx.GetSavedContext(SavedContextType.ReparseMarkupExtension); + PendingKeyConversionContexts.Add(parentCollection, new ObjectWriterContext(savedContext, null, null, Runtime)); + } + } + return true; + } + return false; + } + + private void Logic_DoAssignmentToParentProperty(ObjectWriterContext ctx) + { + XamlMember parentProperty = ctx.ParentProperty; + object value = ctx.CurrentInstance; + + // First look to handle adds to collections. + // Collections are always in a directive of collection or dictionary type. + // oh btw PositionalParameters are the "other" collection property. :-) + XamlType ppXamlType = parentProperty.Type; + if (parentProperty.IsDirective && (ppXamlType.IsCollection || ppXamlType.IsDictionary)) + { + if (value is NameFixupToken && parentProperty != XamlLanguage.Items) + { + NameFixupToken token = value as NameFixupToken; + string names = String.Join(",", token.NeededNames.ToArray()); + string msg = SR.Get(SRID.ForwardRefDirectives, names); + throw ctx.WithLineInfo(new XamlObjectWriterException(msg)); + } + if (parentProperty == XamlLanguage.PositionalParameters) + { + ctx.CurrentType = XamlLanguage.PositionalParameterDescriptor; + ctx.CurrentInstance = new PositionalParameterDescriptor(value, false); + } + Logic_DoAssignmentToParentCollection(ctx); + } + else + { + object parentInstance = ctx.ParentInstance; + if (parentInstance != null) + { + // This checks for multi-values to single valued properties. + // + // Red + // Blue + // Green + // + if (ctx.ParentIsPropertyValueSet) + { + throw ctx.WithLineInfo(new XamlDuplicateMemberException( + ctx.ParentProperty, + ctx.ParentType)); + } + ctx.ParentIsPropertyValueSet = true; + if (value is NameFixupToken) + { + var token = (NameFixupToken)value; + if (parentProperty.IsDirective) + { + // Only the key directive may be assigned a reference. + if (parentProperty != XamlLanguage.Key) + { + string names = String.Join(",", token.NeededNames.ToArray()); + string msg = SR.Get(SRID.ForwardRefDirectives, names); + throw ctx.WithLineInfo(new XamlObjectWriterException(msg)); + } + Logic_PendKeyFixupToken(ctx, token); + } + else + { + Logic_PendCurrentFixupToken_SetValue(ctx, token); + } + } + else + { + XamlType parentType = ctx.ParentType; + + if (!ctx.CurrentIsObjectFromMember) + { + Logic_ApplyPropertyValue(ctx, parentProperty, value, true /*onParent*/); + + // registered a named object + if (parentProperty == parentType.GetAliasedProperty(XamlLanguage.Name)) + { + Logic_RegisterName_OnParent(ctx, (string)value); + } + + if (parentProperty == XamlLanguage.Key) + { + ctx.ParentKey = value; + } + // The other aliases of Uid, Lang, don't have special processing. + } + } + } + else // when parentInstance == null + { + if (parentProperty.IsDirective) + { + // Base Uri must be set on the Context ASAP. It needs to be set before the + // object is constructed. + if (parentProperty == XamlLanguage.Base) + { + Logic_CheckBaseUri(ctx, (string)value); + ctx.BaseUri = new Uri((string)value); + } + else + { + + if (value is NameFixupToken) + { + // Only the key directive may be assigned a reference. + if (parentProperty != XamlLanguage.Key) + { + NameFixupToken token = (NameFixupToken)value; + string names = String.Join(",", token.NeededNames.ToArray()); + string msg = SR.Get(SRID.ForwardRefDirectives, names); + throw ctx.WithLineInfo(new XamlObjectWriterException(msg)); + } + Logic_PendKeyFixupToken(ctx, (NameFixupToken)value); + } + else if (parentProperty == XamlLanguage.Key) + { + ctx.ParentKey = value; + } + else + { + ctx.ParentPreconstructionPropertyValues.Add(parentProperty, value); + } + } + } + else + { + throw new XamlInternalException(SR.Get(SRID.BadStateObjectWriter)); + } + } + } + } + + private void Logic_PendKeyFixupToken(ObjectWriterContext ctx, NameFixupToken token) + { + Debug.Assert(token.Target.Property == XamlLanguage.Key); + + // Keys aren't fixups on the item itself, they're fixups on the KeyHolder that contains it + // Any changes to the Target must also update the actual ObjectWriterFrame itself as well. + token.Target.Instance = ctx.GrandParentInstance; + token.Target.InstanceType = ctx.GrandParentType; + token.Target.InstanceWasGotten = ctx.GrandParentIsObjectFromMember; + FixupTargetKeyHolder ftkh = new FixupTargetKeyHolder(token); + token.Target.KeyHolder = ftkh; + ctx.ParentKey = ftkh; + + // if the grandparent instance is null, we're not in a dictionary, so the key will never be used + // so just throw it away + if (token.Target.Instance != null) + { + Logic_PendCurrentFixupToken_SetValue(ctx, token); + } + } + + private void Logic_RegisterName_OnCurrent(ObjectWriterContext ctx, string name) + { + bool isRoot = ctx.LiveDepth == 1; + RegisterName(ctx, name, ctx.CurrentInstance, ctx.CurrentType, + ctx.CurrentNameScope, ctx.ParentNameScope, isRoot); + ctx.CurrentInstanceRegisteredName = name; + } + + private void Logic_RegisterName_OnParent(ObjectWriterContext ctx, string name) + { + RegisterName(ctx, name, ctx.ParentInstance, ctx.ParentType, + ctx.ParentNameScope, ctx.GrandParentNameScope, false); + ctx.ParentInstanceRegisteredName = name; + } + + private void RegisterName(ObjectWriterContext ctx, string name, + object inst, XamlType xamlType, + INameScope nameScope, INameScope parentNameScope, bool isRoot) + { + INameScope underlyingNameScope = nameScope; + NameScopeDictionary nameScopeDict = nameScope as NameScopeDictionary; + if (nameScopeDict != null) + { + underlyingNameScope = nameScopeDict.UnderlyingNameScope; + } + + // Don't register a named object on itself. Unless this is the root. + if (Object.ReferenceEquals(underlyingNameScope, inst) && !isRoot) + { + // If nameScope was the instance AND it wasn't the root... + // Then use the parent name scope + nameScope = parentNameScope; + } + + // Don't register a name for a FixupToken, that will be done when the converter is rerun + if (!(inst is NameFixupToken)) + { + try + { + nameScope.RegisterName(name, inst); + } + catch (Exception ex) + { + if (CriticalExceptions.IsCriticalException(ex)) + { + throw; + } + throw ctx.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.NameScopeException, ex.Message), ex)); + } + } + } + + private void Logic_SetConnectionId(ObjectWriterContext ctx, int connectionId, object instance) + { + object rootInstance = ctx.RootInstance; + Runtime.SetConnectionId(rootInstance, connectionId, instance); + } + + private void SetValue(Object inst, XamlMember property, object value) + { +#if !TARGETTING35SP1 + if (!property.IsDirective) + { + if (OnSetValue(inst, property, value)) + { + return; + } + } +#endif + + Runtime.SetValue(inst, property, value); + } + + private void Logic_ValidateXClass(ObjectWriterContext ctx, object value) + { + if (ctx.Depth > 1) + { + throw ctx.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.DirectiveNotAtRoot, XamlLanguage.Class))); + } + string className = value as string; + if (className == null) + { + throw ctx.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.DirectiveMustBeString, XamlLanguage.Class))); + } + object curInstance = ctx.CurrentInstance; + Type rootInstanceType = (curInstance != null) ? curInstance.GetType() : ctx.CurrentType.UnderlyingType; + if (rootInstanceType.FullName != className) + { + string rootNamespace = SchemaContext.GetRootNamespace(rootInstanceType.Assembly); + if (!string.IsNullOrEmpty(rootNamespace)) + { + className = rootNamespace + "." + className; + } + if (rootInstanceType.FullName != className) + { + throw ctx.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.XClassMustMatchRootInstance, className, rootInstanceType.FullName))); + } + } + } + + // =========== NameFixupToken Processing ====================== + private void Logic_AddDependencyForUnresolvedChildren(ObjectWriterContext ctx, + XamlSavedContext deferredMarkupExtensionContext) + { + object childThatHasUnresolvedChildren = ctx.CurrentInstance; + XamlMember property = ctx.ParentProperty; + + if (property != null && property.IsDirective && ctx.ParentInstance == null && property != XamlLanguage.Key) + { + // The parent instance is null, so we're in a creation directives. Forward refs + // aren't allowed here. + List names = new List(); + _nameFixupGraph.GetDependentNames(childThatHasUnresolvedChildren, names); + string namesString = string.Join(", ", names.ToArray()); + throw ctx.WithLineInfo(new XamlObjectWriterException(SR.Get(SRID.TransitiveForwardRefDirectives, + childThatHasUnresolvedChildren.GetType(), property, namesString))); + } + + NameFixupToken token = GetTokenForUnresolvedChildren( + childThatHasUnresolvedChildren, property, deferredMarkupExtensionContext); + token.Target.Instance = ctx.ParentInstance; + token.Target.InstanceType = ctx.ParentType; + token.Target.InstanceWasGotten = ctx.ParentIsObjectFromMember; + Logic_PendCurrentFixupToken_SetValue(ctx, token); + } + + private NameFixupToken GetTokenForUnresolvedChildren(object childThatHasUnresolvedChildren, + XamlMember property, XamlSavedContext deferredMarkupExtensionContext) + { + NameFixupToken token = new NameFixupToken(); + if (deferredMarkupExtensionContext != null) + { + token.FixupType = FixupType.MarkupExtensionFirstRun; + token.SavedContext = deferredMarkupExtensionContext; + } + else + { + token.FixupType = FixupType.UnresolvedChildren; + } + token.ReferencedObject = childThatHasUnresolvedChildren; + token.Target.Property = property; + return token; + } + + private void CompleteNameReferences() + { + if (_nameFixupGraph == null) + { + return; + } + + // Step 1. Resolve any pending simple fixups + List unresolvedRefs = null; + IEnumerable simpleFixups = _nameFixupGraph.GetRemainingSimpleFixups(); + foreach (NameFixupToken token in simpleFixups) + { + object namedObject = token.ResolveName(token.NeededNames[0]); + if (namedObject == null) + { + if (unresolvedRefs == null) + { + unresolvedRefs = new List(); + } + unresolvedRefs.Add(token); + } + // Only process if we haven't found any unresolved references. If we have, + // we're going to throw, so no point in processing. + else if (unresolvedRefs == null) + { + token.ReferencedObject = namedObject; + token.NeededNames.RemoveAt(0); + ProcessNameFixup(token, true); + + // We've resolved the reference, but the resolved object must have unresolved + // children, or else the reference wouldn't have remained unresolved until now. + // So we add an UnresolvedChildren dependency, so that we will run EndInit/ProvideValue + // as appropriate in Step 3. + _nameFixupGraph.AddEndOfParseDependency(token.ReferencedObject, token.Target); + } + } + if (unresolvedRefs != null) + { + ThrowUnresolvedRefs(unresolvedRefs); + } + + // Step 2. Run any remaining reparses + IEnumerable reparses = _nameFixupGraph.GetRemainingReparses(); + foreach (NameFixupToken token in reparses) + { + ProcessNameFixup(token, true); + // Add an UnresolvedChildren dependency, for the same reason as in Step 1 above + _nameFixupGraph.AddEndOfParseDependency(token.TargetContext.CurrentInstance, token.Target); + } + + // Step 3. Run all pending ProvideValues and EndInits + IEnumerable objectDependencies = _nameFixupGraph.GetRemainingObjectDependencies(); + foreach (NameFixupToken token in objectDependencies) + { + ProcessNameFixup(token, true); + if (token.Target.Instance != null && + !_nameFixupGraph.HasUnresolvedChildren(token.Target.Instance)) + { + CompleteDeferredInitialization(token.Target); + } + } + } + + // Throw an exception with all the unresolved simple fixups + private void ThrowUnresolvedRefs(IEnumerable unresolvedRefs) + { + StringBuilder exceptionMessage = new StringBuilder(); + bool first = true; + foreach (NameFixupToken token in unresolvedRefs) + { + if (!first) + { + exceptionMessage.AppendLine(); + } + exceptionMessage.Append(SR.Get(SRID.UnresolvedForwardReferences, token.NeededNames[0])); + if (token.LineNumber != 0) + { + if (token.LinePosition != 0) + { + exceptionMessage.Append(SR.Get(SRID.LineNumberAndPosition, string.Empty, token.LineNumber, token.LinePosition)); + } + exceptionMessage.Append(SR.Get(SRID.LineNumberOnly, string.Empty, token.LineNumber)); + } + first = false; + } + throw new XamlObjectWriterException(exceptionMessage.ToString()); + } + + private void TriggerNameResolution(object instance, string name) + { +#if DEBUG + Debug.Assert(!_inNameResolution); + _inNameResolution = true; +#endif + Debug.Assert(_nameFixupGraph != null); + _nameFixupGraph.ResolveDependenciesTo(instance, name); + while (_nameFixupGraph.HasResolvedTokensPendingProcessing) + { + NameFixupToken token = _nameFixupGraph.GetNextResolvedTokenPendingProcessing(); + ProcessNameFixup(token, false); + + // If this was a named type-converted object, and it's already off the stack, then + // it lost its chance to trigger name resolution in WriteEndObject. So resolve any + // dependencies to its name now. + if (token.FixupType == FixupType.ObjectInitializationValue && + !token.CanAssignDirectly && + token.TargetContext.CurrentInstanceRegisteredName != null && + !_context.IsOnTheLiveStack(token.TargetContext.CurrentInstance)) + { + string convertedName = token.TargetContext.CurrentInstanceRegisteredName; + object convertedInstance = token.TargetContext.CurrentInstance; + _nameFixupGraph.ResolveDependenciesTo(convertedInstance, convertedName); + } + + // If this was the last pending fixup for the parent object, then resolve any + // transitive dependencies + bool isComplete = !token.Target.InstanceIsOnTheStack && + !_nameFixupGraph.HasUnresolvedOrPendingChildren(token.Target.Instance); + if (isComplete) + { + CompleteDeferredInitialization(token.Target); + + object completedInstance = token.Target.Instance; + string completedName = token.Target.InstanceName; + _nameFixupGraph.ResolveDependenciesTo(completedInstance, completedName); + } + } +#if DEBUG + _inNameResolution = false; +#endif + } + + bool ICheckIfInitialized.IsFullyInitialized(object instance) + { + if (instance == null) + { + return true; + } + if (_context.LiveDepth > 0) + { + // An object is fully initialized if it's off the stack, and has no uninitialized children + if (_context.IsOnTheLiveStack(instance)) + { + return false; + } + return _nameFixupGraph == null || !_nameFixupGraph.HasUnresolvedOrPendingChildren(instance); + } + else + { + // At the end of the parse, we start running reparses on partially initialized objects, + // and remove those dependencies. But we still want to be able to inform MEs/TCs that + // the named objects they're getting aren't actually fully initialized. So we save a list + // of incompletely initialized objects at the point we started completing references. + return _nameFixupGraph == null || !_nameFixupGraph.WasUninitializedAtEndOfParse(instance); + } + } + + private void CompleteDeferredInitialization(FixupTarget target) + { + ExecutePendingAdds(target.InstanceType, target.Instance); + + if (!target.InstanceWasGotten) + { + IAddLineInfo oldLineInfo = Runtime.LineInfo; + Runtime.LineInfo = target; + try + { + Runtime.InitializationGuard(target.InstanceType, target.Instance, false); + } + finally + { + Runtime.LineInfo = oldLineInfo; + } + + OnAfterEndInit(target.Instance); + } + } + + // Processes a fixup token by assigning the resolved name or rerunning converters, + // and calling EndInit if the token's target object is finally fully initialized. + private void ProcessNameFixup(NameFixupToken token, bool nameResolutionIsComplete) + { + Debug.Assert(token.NeededNames.Count == 0 || nameResolutionIsComplete); + IAddLineInfo oldLineInfo = Runtime.LineInfo; + try + { + Runtime.LineInfo = token; + if (token.CanAssignDirectly) + { + ProcessNameFixup_Simple(token); + } + else if (token.FixupType != FixupType.UnresolvedChildren) + { + ProcessNameFixup_Reparse(token, nameResolutionIsComplete); + } + } + finally + { + Runtime.LineInfo = oldLineInfo; + } + } + + private void ProcessNameFixup_Simple(NameFixupToken token) + { + object value = token.ReferencedObject; + if (token.Target.Property == XamlLanguage.Key) + { + ProcessNameFixup_UpdatePendingAddKey(token, value); + } + else if (token.Target.Property == XamlLanguage.Items) + { + ProcessNameFixup_UpdatePendingAddItem(token, value); + } + else + { + SetValue(token.Target.Instance, token.Target.Property, value); + } + } + + private void ProcessNameFixup_Reparse(NameFixupToken token, bool nameResolutionIsComplete) + { + object value = null; + + var owc = token.TargetContext; + owc.NameResolutionComplete = nameResolutionIsComplete; + owc.IsInitializedCallback = this; + switch (token.FixupType) + { + case FixupType.MarkupExtensionFirstRun: + bool handled = Logic_ProvideValue(owc); + if (handled) + { + return; + } + break; + case FixupType.MarkupExtensionRerun: + // Logic_ProvideValue already ran the first time, no need to rerun it + value = Runtime.CallProvideValue((MarkupExtension)owc.CurrentInstance, owc.ServiceProviderContext); + owc.CurrentInstance = value; + break; + case FixupType.PropertyValue: + value = Logic_CreateFromValue(owc, owc.ParentProperty.TypeConverter, owc.CurrentInstance, + owc.ParentProperty, owc.ParentProperty.Name, token); + token.TargetContext.CurrentInstance = value; + break; + case FixupType.ObjectInitializationValue: + Logic_CreateFromInitializationValue(owc); + if (token.TargetContext.CurrentInstanceRegisteredName != null) + { + // We couldn't actually register before, because the instance hadn't been + // created by the TypeConverter. So register it now. + Logic_RegisterName_OnCurrent(token.TargetContext, token.TargetContext.CurrentInstanceRegisteredName); + } + break; + } + +#if DEBUG + if(token.Target.Property != token.TargetContext.ParentProperty) + { + throw new XamlInternalException("Token's Target Property '{0}' != '{1}' the Token's Context parent Property"); + } +#endif + if (token.Target.Property == XamlLanguage.Key) + { + ProcessNameFixup_UpdatePendingAddKey(token, owc.CurrentInstance); + } + else if (token.Target.Property == XamlLanguage.Items) + { + ProcessNameFixup_UpdatePendingAddItem(token, owc.CurrentInstance); + } + else if (token.Target.Property != null) + { + Logic_DoAssignmentToParentProperty(owc); + } + else + { + // This is a deferred ProvideValue at the root + Debug.Assert(token.FixupType == FixupType.MarkupExtensionFirstRun && _lastInstance == token.ReferencedObject); + _lastInstance = owc.CurrentInstance; + } + + NameFixupToken newToken = owc.CurrentInstance as NameFixupToken; + if (newToken != null) + { + // Line Info should be the same as the original token, not wherever we happen to be currently. + // Also several properties on Target (IsOnTheStack, EndInstanceLineInfo, and potentially others) + // may have been updated on the old token, copy those same updates to the new token. + newToken.Target = token.Target; + newToken.LineNumber = token.LineNumber; + newToken.LinePosition = token.LinePosition; + + // Logic_DoAssignmentToParentProperty will add the dependency for the new token, but + // ProcessNameFixup_UpdatePendingAddKey/Item doesn't. So do that here. + if (token.Target.Property == XamlLanguage.Key || token.Target.Property == XamlLanguage.Items) + { + _nameFixupGraph.AddDependency(newToken); + } + } + } + + private void ProcessNameFixup_UpdatePendingAddKey(NameFixupToken token, object key) + { + if (token.Target.KeyHolder != null) + { + // The KeyHolder item is still on the stack, so update the KeyHolder + Debug.Assert(token.Target.KeyHolder.Key == token); + token.Target.KeyHolder.Key = key; + } + // if the index is less than 0, the target's not a dictionary, so throw away the key + else if (token.Target.TemporaryCollectionIndex >= 0) + { + // The dictionary item is no longer on the stack, so update _pendingCollectionAdds + List pendingCollection = PendingCollectionAdds[token.Target.Instance]; + PendingCollectionAdd pendingAdd = pendingCollection[token.Target.TemporaryCollectionIndex]; + Debug.Assert(pendingAdd.Key == token); + pendingAdd.Key = key; + pendingAdd.KeyIsSet = true; + } + } + + private void ProcessNameFixup_UpdatePendingAddItem(NameFixupToken token, object item) + { + List pendingCollection = PendingCollectionAdds[token.Target.Instance]; + PendingCollectionAdd pendingAdd = pendingCollection[token.Target.TemporaryCollectionIndex]; + Debug.Assert(pendingAdd.Item == token); + pendingAdd.Item = item; + if (!(item is NameFixupToken)) + { + pendingAdd.ItemType = (item != null) ? GetXamlType(item.GetType()) : null; + } + } + + private void ExecutePendingAdds(XamlType instanceType, object instance) + { + List pendingCollection; + if (_pendingCollectionAdds != null && PendingCollectionAdds.TryGetValue(instance, out pendingCollection)) + { + foreach (PendingCollectionAdd pendingAdd in pendingCollection) + { + XamlType itemType = pendingAdd.ItemType ?? instanceType.ItemType; + + IAddLineInfo oldLineInfo = Runtime.LineInfo; + Runtime.LineInfo = pendingAdd; + try + { + if (instanceType.IsDictionary) + { + if (!pendingAdd.KeyIsSet) + { + pendingAdd.Key = GetKeyFromInstance(pendingAdd.Item, itemType, pendingAdd); + pendingAdd.KeyIsSet = true; + } + if (pendingAdd.KeyIsUnconverted) + { + // If the Add of the unconverted key fails, we will need to convert the key. + ObjectWriterContext ctx = PendingKeyConversionContexts[instance]; + ctx.PopScope(); // The saved context will have some dictionary item on top. + ctx.PushScope(); // Pop it and replace it with the current item. + ctx.CurrentType = itemType; + ctx.CurrentInstance = pendingAdd.Item; + ctx.CurrentKeyIsUnconverted = pendingAdd.KeyIsUnconverted; + Logic_AddToParentDictionary(ctx, pendingAdd.Key, pendingAdd.Item); + } + else + { + Runtime.AddToDictionary(instance, instanceType, pendingAdd.Item, itemType, pendingAdd.Key); + } + } + else + { + Runtime.Add(instance, instanceType, pendingAdd.Item, pendingAdd.ItemType); + } + } + finally + { + Runtime.LineInfo = oldLineInfo; + } + } + PendingCollectionAdds.Remove(instance); + if (_pendingKeyConversionContexts != null && _pendingKeyConversionContexts.ContainsKey(instance)) + { + _pendingKeyConversionContexts.Remove(instance); + } + } + } + + private class PendingCollectionAdd : IAddLineInfo + { + public object Key { get; set; } + public bool KeyIsSet { get; set; } // Need this because key could validly be null + public bool KeyIsUnconverted { get; set; } + public object Item { get; set; } + public XamlType ItemType { get; set; } // Need this because Add() overload resolution + // is based on the SO type, which could be different + // from the actual type in case of TCs and FactoryMethods + public int LineNumber { get; set; } + public int LinePosition { get; set; } + + XamlException IAddLineInfo.WithLineInfo(XamlException ex) + { + if (LineNumber > 0) + { + ex.SetLineInfo(LineNumber, LinePosition); + } + return ex; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlObjectWriterSettings.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlObjectWriterSettings.cs new file mode 100644 index 00000000000..be45061fa55 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlObjectWriterSettings.cs @@ -0,0 +1,86 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; +using System.Security; +using System.Security.Permissions; +using System.Xaml.Permissions; + +namespace System.Xaml +{ + public class XamlObjectWriterSettings : XamlWriterSettings + { + public XamlObjectWriterSettings() + { + } + + public XamlObjectWriterSettings(XamlObjectWriterSettings settings) + { + if (settings == null) + { + throw new ArgumentNullException("settings"); + } + AfterBeginInitHandler = settings.AfterBeginInitHandler; + BeforePropertiesHandler = settings.BeforePropertiesHandler; + AfterPropertiesHandler = settings.AfterPropertiesHandler; + AfterEndInitHandler = settings.AfterEndInitHandler; +#if !TARGETTING35SP1 + XamlSetValueHandler = settings.XamlSetValueHandler; +#endif + RootObjectInstance = settings.RootObjectInstance; + IgnoreCanConvert = settings.IgnoreCanConvert; + ExternalNameScope = settings.ExternalNameScope; + SkipDuplicatePropertyCheck = settings.SkipDuplicatePropertyCheck; + RegisterNamesOnExternalNamescope = settings.RegisterNamesOnExternalNamescope; + AccessLevel = settings.AccessLevel; + SkipProvideValueOnRoot = settings.SkipProvideValueOnRoot; + PreferUnconvertedDictionaryKeys = settings.PreferUnconvertedDictionaryKeys; + SourceBamlUri = settings.SourceBamlUri; + } + + public EventHandler AfterBeginInitHandler { get; set; } + public EventHandler BeforePropertiesHandler { get; set; } + public EventHandler AfterPropertiesHandler { get; set; } + public EventHandler AfterEndInitHandler { get; set; } +#if !TARGETTING35SP1 + public EventHandler XamlSetValueHandler { get; set; } +#endif + + public Object RootObjectInstance { get; set; } + public bool IgnoreCanConvert { get; set; } + public System.Windows.Markup.INameScope ExternalNameScope { get; set; } + public bool SkipDuplicatePropertyCheck { get; set; } + public bool RegisterNamesOnExternalNamescope { get; set; } + public bool SkipProvideValueOnRoot { get; set; } + public bool PreferUnconvertedDictionaryKeys { get; set; } + + /// + /// SourceBamlUri will be used by XamlObjectWriter in BeginInitHandler's SourceBamlUri property, in place of the actual BaseUri. + /// This is only useful to give the correct info in that handler, while keeping runtime behavior fully compatible. + /// + public Uri SourceBamlUri { get; set; } + + // Not critical: This property indicates the expected access level for non-public members + // in partial trust. We don't actually make any security decisions based on + // this value without demanding XamlLoadPermission. + public XamlAccessLevel AccessLevel { get; set; } + + internal XamlObjectWriterSettings StripDelegates() + { + XamlObjectWriterSettings result = new XamlObjectWriterSettings(this); + // We need better protection against leaking out these delegates + result.AfterBeginInitHandler = null; + result.AfterEndInitHandler = null; + result.AfterPropertiesHandler = null; + result.BeforePropertiesHandler = null; +#if !TARGETTING35SP1 + result.XamlSetValueHandler = null; +#endif + return result; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlReaderSettings.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlReaderSettings.cs new file mode 100644 index 00000000000..85eb3a20fae --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlReaderSettings.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using System.Reflection; + +namespace System.Xaml +{ + /// + /// The LocalAssembly and AllowProtectedMembersOnRoot properties are not SecurityCritical. + /// XamlXmlReader uses these properties to surface non-public members in the nodestream, but it + /// does not actually enable invocation of those members. + /// XamlObjectReader invokes the non-public members, but does so transparently. + /// Any component which allows invocation of non-public members in partial trust should demand + /// an appropriate permission (such as ReflectionPerission or XamlLoadPermisison). + /// + public class XamlReaderSettings + { + public bool AllowProtectedMembersOnRoot { get; set; } + public bool ProvideLineInfo { get; set; } + public Uri BaseUri { get; set; } + public Assembly LocalAssembly { get; set; } + public bool IgnoreUidsOnPropertyElements { get; set; } + public bool ValuesMustBeString { get; set; } + + public XamlReaderSettings() + { + InitializeProvideLineInfo(); + } + + public XamlReaderSettings(XamlReaderSettings settings) : this() + { + if (settings != null) + { + AllowProtectedMembersOnRoot = settings.AllowProtectedMembersOnRoot; + ProvideLineInfo = settings.ProvideLineInfo; + BaseUri = settings.BaseUri; + LocalAssembly = settings.LocalAssembly; + IgnoreUidsOnPropertyElements = settings.IgnoreUidsOnPropertyElements; + ValuesMustBeString = settings.ValuesMustBeString; + } + } + + private void InitializeProvideLineInfo() + { + //By default, _provideLineInfo is true if the currently executing process is running in debug mode + if (Debugger.IsAttached) + { + ProvideLineInfo = true; + } + else + { + ProvideLineInfo = false; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlTextReader.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlTextReader.cs new file mode 100644 index 00000000000..709b92b8aef --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlTextReader.cs @@ -0,0 +1,219 @@ +using System; +using System.Collections.Generic; +using System.Xml; + +#if SILVERLIGHTXAML +using MS.Internal.Xaml.Parser; +using MS.Internal.Xaml.MS.Impl; +using MS.Internal.Xaml.Context; +#else +using System.Xaml.Parser; +using System.Xaml.MS.Impl; +using System.Windows.Markup; +#endif + +#if SILVERLIGHTXAML +namespace MS.Internal.Xaml +#else +namespace System.Xaml +#endif +{ +#if SILVERLIGHTXAML + internal +#else + public +#endif + class XamlTextReader : XamlReader, IXamlLineInfo + { + XamlParserContext _context; + IEnumerator _nodeStream; + + XamlNode _current; + XamlNode _endOfStreamNode; + + XamlTextReaderSettings _mergedSettings; + + public XamlTextReader(XmlReader xmlReader) + { + Initialize(xmlReader, null, null); + } + + public XamlTextReader(XmlReader xmlReader, XamlTextReaderSettings settings) + { + Initialize(xmlReader, null, settings); + } + + public XamlTextReader(XmlReader xmlReader, XamlSchemaContext schemaContext) + { + if (schemaContext == null) + throw new ArgumentNullException("schemaContext"); + + Initialize(xmlReader, schemaContext, null); + } + + public XamlTextReader(XmlReader xmlReader, XamlSchemaContext schemaContext, XamlTextReaderSettings settings) + { + if (schemaContext == null) + throw new ArgumentNullException("schemaContext"); + + Initialize(xmlReader, schemaContext, settings); + } + + private void Initialize(XmlReader givenXmlReader, XamlSchemaContext schemaContext, XamlTextReaderSettings settings) + { + XmlReader myXmlReader; + + if (givenXmlReader == null) + { + throw new ArgumentNullException("XmlReader is null"); + } + + _mergedSettings = (settings == null) ? new XamlTextReaderSettings() : new XamlTextReaderSettings(settings); + + //Wrap the xmlreader with a XmlCompatReader instance to apply MarkupCompat rules. + if (!_mergedSettings.SkipXmlCompatibilityProcessing) + { + XmlCompatibilityReader mcReader = + new XmlCompatibilityReader(givenXmlReader, + new IsXmlNamespaceSupportedCallback(IsXmlNamespaceSupported) + ); + myXmlReader = mcReader; + } + else + { // Don't wrap the xmlreader with XmlCompatReader. + // Useful for uses where users want to keep mc: content in the XamlNode stream. + // Or have already processed the markup compat and want that extra perf. + // We need to go make sure the parser thinks it knows mc: uri, + // in case SkipXmlCompatibilityProcessing is true... likely won't work yet. + myXmlReader = givenXmlReader; + } + // Pick up the XmlReader settings to override the "settings" defaults. + if (!String.IsNullOrEmpty(myXmlReader.BaseURI)) + { + _mergedSettings.BaseUri = new Uri(myXmlReader.BaseURI); + } + if (myXmlReader.XmlSpace == XmlSpace.Preserve) + { + _mergedSettings.XmlSpacePreserve = true; + } + if (!String.IsNullOrEmpty(myXmlReader.XmlLang)) + { + _mergedSettings.XmlLang = myXmlReader.XmlLang; + } + + if (schemaContext == null) + { + schemaContext = new XamlSchemaContext(); + } + + _endOfStreamNode = new InternalNode(InternalNodeType.EndOfStream); + + _context = (XamlParserContext)XamlContext.CreateContext(UsageMode.Parser, schemaContext, + _mergedSettings.LocalAssembly, false /*ignoreCanConvert*/); + + XamlScanner xamlScanner = new XamlScanner(_context, myXmlReader, _mergedSettings); + XamlPullParser parser = new XamlPullParser(_context, xamlScanner, _mergedSettings); + _nodeStream = new NodeStreamSorter(_context, parser, _mergedSettings); + _current = _endOfStreamNode; // user must call Read() before using properties. + } + + #region XamlReader Members + + public override bool Read() + { + if (_nodeStream.MoveNext()) + { + _current = _nodeStream.Current; + } + else + { + _current = _endOfStreamNode; + } + return !IsEof; + } + + public override XamlNodeType NodeType + { + get { return _current.NodeType; } + } + + public override bool IsEof + { + get { return XamlNode.IsEof(_current); } + } + + public override NamespaceDeclaration Namespace + { + get { return XamlNode.GetNamespaceDeclaration(_current); } + } + + public override XamlType Type + { + get { return XamlNode.GetXamlType(_current); } + } + + public override object Value + { + get { return XamlNode.GetValue(_current); } + } + + public override XamlProperty Member + { + get { return XamlNode.GetMember(_current); } + } + + public override XamlSchemaContext SchemaContext + { + get { return _context.SchemaContext; } + } + + public override bool IsObjectFromMember + { + get { return XamlNode.GetIsObjectFromMember(_current); } + } + + #endregion + + #region IXamlLineInfo Members + + public bool HasLineInfo + { + get { return _mergedSettings.ProvideLineInfo; } + } + + public int LineNumber + { + get { return XamlNode.GetLineNumber(_current); } + } + + public int LinePosition + { + get { return XamlNode.GetLinePosition(_current); } + } + + #endregion + + // Return true if the passed namespace is known, meaning that it maps + // to a set of assemblies and clr namespaces + internal bool IsXmlNamespaceSupported(string xmlNamespace, out string newXmlNamespace) + { + newXmlNamespace = null; + + bool isSupported = _context.SchemaContext.XamlNamespaceExists(xmlNamespace, _mergedSettings.LocalAssembly); + newXmlNamespace = xmlNamespace; // should probalby be upgraded via CompatibleWith + + // we should treat all namespaces inside of XmlDataIslands as Supported. + return isSupported; + + // we need to tree Freeze as known, if it is around... don't hardcode. + //else if (xmlNamespace == XamlReaderHelper.PresentationOptionsNamespaceURI) + //{ + // // PresentationOptions is expected to be marked as 'ignorable' in most Xaml + // // so that other Xaml parsers don't have to interpret it, but this parser + // // does handle it to support it's Freeze attribute. + // return true; + //} + } + + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlTextReaderSettings.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlTextReaderSettings.cs new file mode 100644 index 00000000000..7c884520206 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlTextReaderSettings.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using System.Reflection; + +#if SILVERLIGHTXAML +namespace MS.Internal.Xaml +#else +namespace System.Xaml +#endif +{ +#if SILVERLIGHTXAML + internal +#else + public +#endif + class XamlTextReaderSettings: XamlReaderSettings + { + public string XmlLang { get; set; } + public bool XmlSpacePreserve { get; set; } + public bool SkipXmlCompatibilityProcessing { get; set; } + + private Dictionary _xmlnsDictionary; + + public XamlTextReaderSettings() + { + _xmlnsDictionary = new Dictionary(); + } + + public XamlTextReaderSettings(XamlTextReaderSettings settings) : base(settings) + { + if (settings == null) + { + _xmlnsDictionary = new Dictionary(); + } + else + { + _xmlnsDictionary = settings._xmlnsDictionary; + XmlLang = settings.XmlLang; + XmlSpacePreserve = settings.XmlSpacePreserve; + SkipXmlCompatibilityProcessing = settings.SkipXmlCompatibilityProcessing; + } + } + + public void AddNamespace(string prefix, string XamlNamespaceUri) + { + _xmlnsDictionary.Add(prefix, XamlNamespaceUri); + } + + public Dictionary XmlnsDictionary + { + get { return _xmlnsDictionary; } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlXmlReader.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlXmlReader.cs new file mode 100644 index 00000000000..7a205ad1a6a --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlXmlReader.cs @@ -0,0 +1,450 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Xml; +using MS.Internal.Xaml; +using MS.Internal.Xaml.Context; +using MS.Internal.Xaml.Parser; +using System.Xaml.MS.Impl; +using System.Windows.Markup; +using System.Xaml; +using System.Xaml.Schema; +using System.Diagnostics; +using System.IO; + +namespace System.Xaml +{ + public class XamlXmlReader : XamlReader, IXamlLineInfo + { + XamlParserContext _context; + IEnumerator _nodeStream; + + XamlNode _current; + LineInfo _currentLineInfo; + XamlNode _endOfStreamNode; + + XamlXmlReaderSettings _mergedSettings; + + public XamlXmlReader(XmlReader xmlReader) + { + if (xmlReader == null) + { + throw new ArgumentNullException("xmlReader"); + } + + Initialize(xmlReader, null, null); + } + + public XamlXmlReader(XmlReader xmlReader, XamlXmlReaderSettings settings) + { + if (xmlReader == null) + { + throw new ArgumentNullException("xmlReader"); + } + + Initialize(xmlReader, null, settings); + } + + public XamlXmlReader(XmlReader xmlReader, XamlSchemaContext schemaContext) + { + if (schemaContext == null) + { + throw new ArgumentNullException("schemaContext"); + } + if (xmlReader == null) + { + throw new ArgumentNullException("xmlReader"); + } + + Initialize(xmlReader, schemaContext, null); + } + + public XamlXmlReader(XmlReader xmlReader, XamlSchemaContext schemaContext, XamlXmlReaderSettings settings) + { + if (schemaContext == null) + { + throw new ArgumentNullException("schemaContext"); + } + if (xmlReader == null) + { + throw new ArgumentNullException("xmlReader"); + } + + Initialize(xmlReader, schemaContext, settings); + } + + public XamlXmlReader(string fileName) + { + if (fileName == null) + { + throw new ArgumentNullException("fileName"); + } + Initialize(CreateXmlReader(fileName, null), null, null); + } + + public XamlXmlReader(string fileName, XamlXmlReaderSettings settings) + { + if (fileName == null) + { + throw new ArgumentNullException("fileName"); + } + + Initialize(CreateXmlReader(fileName, settings), null, settings); + } + + public XamlXmlReader(string fileName, XamlSchemaContext schemaContext) + { + if (fileName == null) + { + throw new ArgumentNullException("fileName"); + } + if (schemaContext == null) + { + throw new ArgumentNullException("schemaContext"); + } + + Initialize(CreateXmlReader(fileName, null), schemaContext, null); + } + + public XamlXmlReader(string fileName, XamlSchemaContext schemaContext, XamlXmlReaderSettings settings) + { + if (fileName == null) + { + throw new ArgumentNullException("fileName"); + } + if (schemaContext == null) + { + throw new ArgumentNullException("schemaContext"); + } + + Initialize(CreateXmlReader(fileName, settings), schemaContext, settings); + } + + private XmlReader CreateXmlReader(string fileName, XamlXmlReaderSettings settings) + { + bool closeInput = (settings == null) ? true : settings.CloseInput; + return XmlReader.Create(fileName, new XmlReaderSettings { CloseInput = closeInput, DtdProcessing = DtdProcessing.Prohibit }); + } + + public XamlXmlReader(Stream stream) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + Initialize(CreateXmlReader(stream, null), null, null); + } + + public XamlXmlReader(Stream stream, XamlXmlReaderSettings settings) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + Initialize(CreateXmlReader(stream, settings), null, settings); + } + + public XamlXmlReader(Stream stream, XamlSchemaContext schemaContext) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + if (schemaContext == null) + { + throw new ArgumentNullException("schemaContext"); + } + + Initialize(CreateXmlReader(stream, null), schemaContext, null); + } + + public XamlXmlReader(Stream stream, XamlSchemaContext schemaContext, XamlXmlReaderSettings settings) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + if (schemaContext == null) + { + throw new ArgumentNullException("schemaContext"); + } + + Initialize(CreateXmlReader(stream, settings), schemaContext, settings); + } + + private XmlReader CreateXmlReader(Stream stream, XamlXmlReaderSettings settings) + { + bool closeInput = (settings != null) && settings.CloseInput; + return XmlReader.Create(stream, new XmlReaderSettings { CloseInput = closeInput, DtdProcessing = DtdProcessing.Prohibit }); + } + + public XamlXmlReader(TextReader textReader) + { + if (textReader == null) + { + throw new ArgumentNullException("textReader"); + } + Initialize(CreateXmlReader(textReader, null), null, null); + } + + public XamlXmlReader(TextReader textReader, XamlXmlReaderSettings settings) + { + if (textReader == null) + { + throw new ArgumentNullException("textReader"); + } + Initialize(CreateXmlReader(textReader, settings), null, settings); + } + + public XamlXmlReader(TextReader textReader, XamlSchemaContext schemaContext) + { + if (textReader == null) + { + throw new ArgumentNullException("textReader"); + } + if (schemaContext == null) + { + throw new ArgumentNullException("schemaContext"); + } + + Initialize(CreateXmlReader(textReader, null), schemaContext, null); + } + + public XamlXmlReader(TextReader textReader, XamlSchemaContext schemaContext, XamlXmlReaderSettings settings) + { + if (textReader == null) + { + throw new ArgumentNullException("textReader"); + } + if (schemaContext == null) + { + throw new ArgumentNullException("schemaContext"); + } + + Initialize(CreateXmlReader(textReader, settings), schemaContext, settings); + } + + private XmlReader CreateXmlReader(TextReader textReader, XamlXmlReaderSettings settings) + { + bool closeInput = (settings != null) && settings.CloseInput; + return XmlReader.Create(textReader, new XmlReaderSettings { CloseInput = closeInput, DtdProcessing = DtdProcessing.Prohibit }); + } + + private void Initialize(XmlReader givenXmlReader, XamlSchemaContext schemaContext, XamlXmlReaderSettings settings) + { + XmlReader myXmlReader; + + _mergedSettings = (settings == null) ? new XamlXmlReaderSettings() : new XamlXmlReaderSettings(settings); + //Wrap the xmlreader with a XmlCompatReader instance to apply MarkupCompat rules. + if (!_mergedSettings.SkipXmlCompatibilityProcessing) + { + XmlCompatibilityReader mcReader = + new XmlCompatibilityReader(givenXmlReader, + new IsXmlNamespaceSupportedCallback(IsXmlNamespaceSupported) + ); + mcReader.Normalization = true; + myXmlReader = mcReader; + } + else + { //Don't wrap the xmlreader with XmlCompatReader. + // Useful for uses where users want to keep mc: content in the XamlNode stream. + // Or have already processed the markup compat and want that extra perf. + myXmlReader = givenXmlReader; + } + // Pick up the XmlReader settings to override the "settings" defaults. + if (!String.IsNullOrEmpty(myXmlReader.BaseURI)) + { + _mergedSettings.BaseUri = new Uri(myXmlReader.BaseURI); + } + if (myXmlReader.XmlSpace == XmlSpace.Preserve) + { + _mergedSettings.XmlSpacePreserve = true; + } + if (!String.IsNullOrEmpty(myXmlReader.XmlLang)) + { + _mergedSettings.XmlLang = myXmlReader.XmlLang; + } + IXmlNamespaceResolver myXmlReaderNS = myXmlReader as IXmlNamespaceResolver; + Dictionary xmlnsDictionary = null; + if (myXmlReaderNS != null) + { + IDictionary rootNamespaces = myXmlReaderNS.GetNamespacesInScope(XmlNamespaceScope.Local); + if (rootNamespaces != null) + { + foreach (KeyValuePair ns in rootNamespaces) + { + if (xmlnsDictionary == null) + { + xmlnsDictionary = new Dictionary(); + } + xmlnsDictionary[ns.Key] = ns.Value; + } + } + } + + if (schemaContext == null) + { + schemaContext = new XamlSchemaContext(); + } + + _endOfStreamNode = new XamlNode(XamlNode.InternalNodeType.EndOfStream); + + _context = new XamlParserContext(schemaContext, _mergedSettings.LocalAssembly); + _context.AllowProtectedMembersOnRoot = _mergedSettings.AllowProtectedMembersOnRoot; + _context.AddNamespacePrefix(KnownStrings.XmlPrefix, XamlLanguage.Xml1998Namespace); + + Func namespaceResolver = myXmlReader.LookupNamespace; + _context.XmlNamespaceResolver = namespaceResolver; + + XamlScanner xamlScanner = new XamlScanner(_context, myXmlReader, _mergedSettings); + XamlPullParser parser = new XamlPullParser(_context, xamlScanner, _mergedSettings); + _nodeStream = new NodeStreamSorter(_context, parser, _mergedSettings, xmlnsDictionary); + _current = new XamlNode(XamlNode.InternalNodeType.StartOfStream); // user must call Read() before using properties. + _currentLineInfo = new LineInfo(0, 0); + } + + #region XamlReader Members + + public override bool Read() + { + ThrowIfDisposed(); + do + { + if (_nodeStream.MoveNext()) + { + _current = _nodeStream.Current; + if (_current.NodeType == XamlNodeType.None) + { + if (_current.LineInfo != null) + { + _currentLineInfo = _current.LineInfo; + } + else if (_current.IsEof) + { + break; + } + else + { + Debug.Assert(_current.IsEof, "Xaml Parser returned an illegal internal XamlNode"); + } + } + } + else + { + _current = _endOfStreamNode; + break; + } + } while (_current.NodeType == XamlNodeType.None); + return !IsEof; + } + + public override XamlNodeType NodeType + { + get { return _current.NodeType; } + } + + public override bool IsEof + { + get { return _current.IsEof; } + } + + public override NamespaceDeclaration Namespace + { + get { return _current.NamespaceDeclaration; } + } + + public override XamlType Type + { + get { return _current.XamlType; } + } + + public override object Value + { + get { return _current.Value; } + } + + public override XamlMember Member + { + get { return _current.Member; } + } + + public override XamlSchemaContext SchemaContext + { + get { return _context.SchemaContext; } + } + + #endregion + + #region IXamlLineInfo Members + + public bool HasLineInfo + { + get { return _mergedSettings.ProvideLineInfo; } + } + + public int LineNumber + { + get { return _currentLineInfo.LineNumber; } + } + + public int LinePosition + { + get { return _currentLineInfo.LinePosition; } + } + + #endregion + + private void ThrowIfDisposed() + { + if (IsDisposed) + { + throw new ObjectDisposedException("XamlXmlReader"); + } + } + + // Return true if the passed namespace is known, meaning that it maps + // to a set of assemblies and clr namespaces + internal bool IsXmlNamespaceSupported(string xmlNamespace, out string newXmlNamespace) + { + // 4 cases: refer to Framework\XamlParser.IsXmlNamespaceSupported + // startins with clr-namespace: + // Namespace is known + // http://schemas.microsoft.com/winfx/2006/xaml/presentation/options + // We're inside of a XmlDataIsland + + // First, substitute in the LocalAssembly if needed + if (_mergedSettings.LocalAssembly != null) + { + string clrNs, assemblyName; + if (ClrNamespaceUriParser.TryParseUri(xmlNamespace, out clrNs, out assemblyName) && + String.IsNullOrEmpty(assemblyName)) + { + assemblyName = _mergedSettings.LocalAssembly.FullName; + newXmlNamespace = ClrNamespaceUriParser.GetUri(clrNs, assemblyName); + return true; + } + } + + bool result = _context.SchemaContext.TryGetCompatibleXamlNamespace(xmlNamespace, out newXmlNamespace); + if (newXmlNamespace == null) + { + newXmlNamespace = string.Empty; + } + + + // we need to treat all namespaces inside of XmlDataIslands as Supported. + // we need to tree Freeze as known, if it is around... don't hardcode. + //else if (xmlNamespace == XamlReaderHelper.PresentationOptionsNamespaceURI) + //{ + // // PresentationOptions is expected to be marked as 'ignorable' in most Xaml + // // so that other Xaml parsers don't have to interpret it, but this parser + // // does handle it to support it's Freeze attribute. + // return true; + //} + return result; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlXmlReaderSettings.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlXmlReaderSettings.cs new file mode 100644 index 00000000000..dddd1c73e88 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/InfosetObjects/XamlXmlReaderSettings.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; +using System.Reflection; + +namespace System.Xaml +{ + public class XamlXmlReaderSettings : XamlReaderSettings + { + public string XmlLang { get; set; } + public bool XmlSpacePreserve { get; set; } + public bool SkipXmlCompatibilityProcessing { get; set; } + public bool CloseInput { get; set; } + + internal Dictionary _xmlnsDictionary; + + public XamlXmlReaderSettings() + { + } + + public XamlXmlReaderSettings(XamlXmlReaderSettings settings) + : base(settings) + { + if (settings != null) + { + if (settings._xmlnsDictionary != null) + { + _xmlnsDictionary = new Dictionary(settings._xmlnsDictionary); + } + XmlLang = settings.XmlLang; + XmlSpacePreserve = settings.XmlSpacePreserve; + SkipXmlCompatibilityProcessing = settings.SkipXmlCompatibilityProcessing; + CloseInput = settings.CloseInput; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/ArrayHelper.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/ArrayHelper.cs new file mode 100644 index 00000000000..f66480eab3c --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/ArrayHelper.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Xaml +{ + internal static class ArrayHelper + { + internal static S[] ConvertArrayType(ICollection src, Func f) + { + if (src == null) + { + return null; + } + int len = src.Count, n = 0; + S[] dest = new S[len]; + foreach (R r in src) + { + dest[n++] = f(r); + } + return dest; + } + + internal static void ForAll(R[] src, Action f) + { + foreach (R r in src) + f(r); + } + + internal static List ToList(IEnumerable src) + { + return (src != null) + ? new List(src) + : null; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/AssemblyNamespacePair.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/AssemblyNamespacePair.cs new file mode 100644 index 00000000000..3b7d14a3724 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/AssemblyNamespacePair.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Reflection; +using System.Diagnostics; + +namespace System.Xaml.MS.Impl +{ + [DebuggerDisplay("{ClrNamespace} {Assembly.FullName}")] + internal class AssemblyNamespacePair + { + WeakReference _assembly; + String _clrNamespace; + + public AssemblyNamespacePair(Assembly asm, String clrNamespace) + { + _assembly = new WeakReference(asm); + _clrNamespace = clrNamespace; + } + + public Assembly Assembly + { + get { return (Assembly)_assembly.Target; } + } + + public string ClrNamespace + { + get { return _clrNamespace; } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/ConcurrentDictionary.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/ConcurrentDictionary.cs new file mode 100644 index 00000000000..68fe4f906fe --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/ConcurrentDictionary.cs @@ -0,0 +1,215 @@ +using System; +using System.Collections.Generic; + +namespace System.xaml.MS.Impl +{ + // For use on 3.5, where there's no ConcurrentDictionary in mscorlib + internal class ConcurrentDictionary : IDictionary + { + private System.Collections.Hashtable _hashtable; + + public ConcurrentDictionary() + { + _hashtable = new System.Collections.Hashtable(); + } + + public void Add(K key, V value) + { + object val = CheckValue(value); + lock (_hashtable) + { + _hashtable.Add(key, val); + } + } + + public bool ContainsKey(K key) + { + return _hashtable.ContainsKey(key); + } + + public ICollection Keys + { + get + { + List result = new List(_hashtable.Count); + lock (_hashtable) + { + foreach (object key in _hashtable.Keys) + { + result.Add((K)key); + } + } + return result.AsReadOnly(); + } + } + + public bool Remove(K key) + { + lock (_hashtable) + { + if (_hashtable.ContainsKey(key)) + { + _hashtable.Remove(key); + return true; + } + return false; + } + } + + public bool TryGetValue(K key, out V value) + { + object result = _hashtable[key]; + if (result == null) + { + value = default(V); + return false; + } + value = (V)result; + return true; + } + + public ICollection Values + { + get + { + List result = new List(_hashtable.Count); + lock (_hashtable) + { + foreach (object value in _hashtable.Values) + { + result.Add((V)value); + } + } + return result.AsReadOnly(); + } + } + + public V this[K key] + { + get + { + object result = _hashtable[key]; + if (result == null) + { + throw new KeyNotFoundException(); + } + return (V)result; + } + set + { + object val = CheckValue(value); + lock (_hashtable) + { + _hashtable[key] = val; + } + } + } + + public void Clear() + { + _hashtable.Clear(); + } + + public int Count + { + get { return _hashtable.Count; } + } + + public IEnumerator> GetEnumerator() + { + List> result = new List>(); + lock (_hashtable) + { + foreach (System.Collections.DictionaryEntry entry in _hashtable) + { + result.Add(new KeyValuePair((K)entry.Key, (V)entry.Value)); + } + } + return result.GetEnumerator(); + } + + public bool TryAdd(K key, V value) + { + object val = CheckValue(value); + lock (_hashtable) + { + if (_hashtable.ContainsKey(key)) + { + return false; + } + _hashtable.Add(key, val); + return true; + } + } + + public bool TryUpdate(K key, V value, V comparand) + { + IEqualityComparer comparer = EqualityComparer.Default; + object val = CheckValue(value); + lock (_hashtable) + { + object existingValue = _hashtable[key]; + if (existingValue == null) + { + return false; + } + if (comparer.Equals((V)existingValue, comparand)) + { + _hashtable[key] = val; + return true; + } + return false; + } + } + + // We don't allow null because otherwise we have no way of distinguishing null from unset + // without taking a lock on read + private object CheckValue(V value) + { + object result = value; + if (result == null) + { + throw new ArgumentNullException("value"); + } + return result; + } + + #region ICollection> Members + + public void Add(KeyValuePair item) + { + throw new NotImplementedException(); + } + + public bool Contains(KeyValuePair item) + { + throw new NotImplementedException(); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public bool IsReadOnly + { + get { return false; } + } + + public bool Remove(KeyValuePair item) + { + throw new NotImplementedException(); + } + + #endregion + + #region IEnumerable Members + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + #endregion + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/KnownStrings.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/KnownStrings.cs new file mode 100644 index 00000000000..899f89c96a3 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/KnownStrings.cs @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Globalization; + +namespace System.Xaml.MS.Impl +{ + internal static class KnownStrings + { + // Built-in strings. + public const string XmlPrefix = "xml"; + public const string XmlNsPrefix = "xmlns"; + + public const string Preserve = "preserve"; + public const string Default = "default"; + + public const string UriClrNamespace = "clr-namespace"; + public const string UriAssembly = "assembly"; + + public const string StringType = "String"; + public const string ObjectType = "Object"; + + public const string Get = "Get"; + public const string Set = "Set"; + public const string Add = "Add"; + public const string Handler = "Handler"; + public const string Extension = "Extension"; + public const string IsReadOnly = "IsReadOnly"; + public const string ShouldSerialize = "ShouldSerialize"; + + public const string FrameworkElement = "FrameworkElement"; // workaround for top-down (may be not used anymore); + public const string TypeExtension = "TypeExtension"; // workaround to work around x:Type having two, single arg Ctors. + + public const char GraveQuote = '`'; + public const char NestedTypeDelimiter = '+'; + public const string GetEnumerator = "GetEnumerator"; + public const string ICollectionOfT = "System.Collections.Generic.ICollection`1"; + public const string IDictionary = "System.Collections.IDictionary"; + public const string IDictionaryOfKT = "System.Collections.Generic.IDictionary`2"; + public const string NullableOfT = "Nullable`1"; + public const string KeyValuePairOfTT = "KeyValuePair`2"; + + public const string AmbientPropertyAttribute = "AmbientPropertyAttribute"; + + public const string DependencyPropertySuffix = "Property"; + public const string XpsNamespace = "http://schemas.microsoft.com/xps/2005/06"; //ideally wouldn't need to workaround this, so wouldn't even need to know it. + + public const string LocalPrefix = "local"; + public const string DefaultPrefix = "p"; + + public const string ReferenceName = "__ReferenceID"; + public static readonly char[] WhitespaceChars = new char[] { ' ', '\t', '\n', '\r', '\f' }; + public static readonly char SpaceChar = ' '; + public static readonly char TabChar = '\t'; + public static readonly char NewlineChar = '\n'; + public static readonly char ReturnChar = '\r'; + + public const string ClrNamespaceFormat = @"clr-namespace:{0};assembly={1}"; + + public const string CreateDelegateHelper = "_CreateDelegate"; + public const string CreateDelegate = "CreateDelegate"; + public const string InvokeMember = "InvokeMember"; + public const string GetTypeFromHandle = "GetTypeFromHandle"; + + public const string Member = "Member"; + public const string Property = "Property"; + } + + // String compare and formating class. + // To control standards of Localization and generally keep FxCop under control. + // + internal static class KS + { + // Standard String Compare operation. + public static bool Eq(String a, String b) + { + return String.Equals(a, b, StringComparison.Ordinal); + } + + // Standard String Compare operation. (ignore case) + // FxCop says this is never called + //public static bool EqNoCase(String a, String b) + //{ + // return String.Equals(a, b, StringComparison.OrdinalIgnoreCase); + //} + + // Standard String Index search operation. + public static int IndexOf(string src, string chars) + { + return src.IndexOf(chars, StringComparison.Ordinal); + } + + public static bool EndsWith(string src, string target) + { + return src.EndsWith(target, StringComparison.Ordinal); + } + + public static bool StartsWith(string src, string target) + { + return src.StartsWith(target, StringComparison.Ordinal); + } + + public static string Fmt(string formatString, params object[] otherArgs) + { + IFormatProvider provider = TypeConverterHelper.InvariantEnglishUS; + string str = String.Format(provider, formatString, otherArgs); + return str; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/PositionalParameterDescriptor.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/PositionalParameterDescriptor.cs new file mode 100644 index 00000000000..65089270240 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/PositionalParameterDescriptor.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Xaml.MS.Impl +{ + internal class PositionalParameterDescriptor + { + public object Value { get; set; } + public bool WasText { get; set; } + + public PositionalParameterDescriptor(object value, bool wasText) + { + Value = value; + WasText = wasText; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XamlDirectiveCollection.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XamlDirectiveCollection.cs new file mode 100644 index 00000000000..744088e0766 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XamlDirectiveCollection.cs @@ -0,0 +1,214 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Windows.Markup; +using System.Collections.ObjectModel; +using System.Text; + +#if SILVERLIGHTXAML +using MS.Internal.Xaml.Schema; +#else +using System.Xaml.Schema; +#endif + +#if SILVERLIGHTXAML +namespace MS.Internal.Xaml.MS.Impl +#else +namespace System.Xaml.MS.Impl +#endif +{ + internal class XamlDirectiveCollection + { + Dictionary _properties; + Dictionary _elements; + + public XamlDirectiveCollection(XamlSchemaContext context, DirectiveInfo[] infos) + { + _properties = new Dictionary(); + _elements = new Dictionary(); + if (infos != null) + { + foreach (DirectiveInfo info in infos) + { + if (info is DirectivePropertyInfo) + { + DirectivePropertyInfo dpi = info as DirectivePropertyInfo; + DirectiveProperty dirProperty = new DirectiveProperty(context, dpi); + _properties.Add(dpi.Name, dirProperty); + } + if (info is DirectiveTypeInfo) + { + DirectiveTypeInfo dti = info as DirectiveTypeInfo; + XamlType xamlType = new XamlType(dti.Type, context); + _elements.Add(dti.Name, xamlType); + } + } + } + } + + public XamlProperty GetDirectiveProperty(string name) + { + DirectiveProperty dirProperty; + _properties.TryGetValue(name, out dirProperty); + return dirProperty; + } + + public XamlType GetDirectiveElement(string name) + { + XamlType dirType; + _elements.TryGetValue(name, out dirType); + return dirType; + } + } + + internal class DirectiveInfo + { + public readonly string Name; + public readonly Type Type; + + public DirectiveInfo(string name, Type type) + { + Name = name; + Type = type; + } + } + + [DebuggerDisplay("{Name} typeof({Type.Name} Loc:{AllowedLocation})")] + internal class DirectivePropertyInfo : DirectiveInfo + { + public readonly XamlTextSyntax TextSyntax; + public readonly AllowedMemberLocation AllowedLocation; + public readonly IList NamespaceList; + + public DirectivePropertyInfo(string name, Type type, XamlTextSyntax ts, AllowedMemberLocation location, IList namespaceList) + :base(name, type) + { + TextSyntax = ts; + AllowedLocation = location; + NamespaceList = namespaceList; + } + } + + internal class DirectiveTypeInfo : DirectiveInfo + { + public DirectiveTypeInfo(Type type) + : base(type.Name, type) { } + public DirectiveTypeInfo(string name, Type type) : base(name, type) { } + } + + internal static class Xaml2006Directives + { + public const string PreferredPrefix = "x"; + public const string Uri = "http://schemas.microsoft.com/winfx/2006/xaml"; + public static ReadOnlyCollection NamespaceList = new ReadOnlyCollection(new Collection() { Xaml2006Directives.Uri }); + + // Properties + public const string x_TypeArguments = "TypeArguments"; + public const string x_Class = "Class"; + public const string x_Key = "Key"; + public const string x_Name = "Name"; + public const string x_Uid = "Uid"; + public const string x_SynchronousMode = "SynchronousMode"; + public const string x_ClassModifier = "ClassModifier"; + public const string x_FieldModifier = "FieldModifier"; + public const string x_FactoryMethod = "FactoryMethod"; + public const string x_Arguments = "Arguments"; + public const string x_ConnectionId = "ConnectionId"; + public const string x_Shared = "Shared"; + public const string x_AsyncRecords = "AsyncRecords"; + + // Elements + public const string x_XData = "XData"; + + // Types + public const string x_Type = "Type"; + public const string x_Null = "Null"; + + public static DirectiveInfo[] DirectiveInfoTable = new DirectiveInfo[] { + // Properties + new DirectivePropertyInfo(x_Class, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.Attribute, Xaml2006Directives.NamespaceList), + + new DirectivePropertyInfo(x_Key, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.Any, Xaml2006Directives.NamespaceList), + + new DirectivePropertyInfo(x_Name, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.Attribute, Xaml2006Directives.NamespaceList), + + new DirectivePropertyInfo(x_Uid, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.Attribute, Xaml2006Directives.NamespaceList), + + new DirectivePropertyInfo(x_SynchronousMode, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.Attribute, Xaml2006Directives.NamespaceList), + + new DirectivePropertyInfo(x_ClassModifier, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.Attribute, Xaml2006Directives.NamespaceList), + + new DirectivePropertyInfo(x_FieldModifier, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.Attribute, Xaml2006Directives.NamespaceList), + + new DirectivePropertyInfo(x_TypeArguments, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.Attribute, Xaml2006Directives.NamespaceList), + + new DirectivePropertyInfo(x_FactoryMethod, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.Any, Xaml2006Directives.NamespaceList), + + new DirectivePropertyInfo(x_Arguments, typeof(List), XamlTextSyntax.NoSyntax, + AllowedMemberLocation.MemberElement, Xaml2006Directives.NamespaceList), + + new DirectivePropertyInfo(x_ConnectionId, typeof(string), XamlTextSyntax.Int32Syntax, + AllowedMemberLocation.Any, Xaml2006Directives.NamespaceList), + + new DirectivePropertyInfo(x_Shared, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.Attribute, Xaml2006Directives.NamespaceList), + + new DirectivePropertyInfo(x_AsyncRecords, typeof(string), XamlTextSyntax.Int32Syntax, + AllowedMemberLocation.Attribute, Xaml2006Directives.NamespaceList), + + // Real CLR types added to this namespace. + // **IMPORTANT** + // All types listed in this datastructure also need to be listed in XamlTypeList below (and vice versa) + new DirectiveTypeInfo(x_Type, typeof(System.Xaml.Replacements.TypeExtension)), + new DirectiveTypeInfo(typeof(String)), + new DirectiveTypeInfo(typeof(Int32)), + new DirectiveTypeInfo(typeof(Boolean)), + new DirectiveTypeInfo(typeof(Double)), + new DirectiveTypeInfo(typeof(Reference)), + }; + + // Real CLR types added to this namespace. + // **IMPORTANT** + // All types listed in this datastructure also need to be listed in the bottom of the DirectiveInfoTable above (and vice versa). + // We use Dictionary since HashTable still requires a 2nd parameter to Add. We actually don't need T (the object), so just pass in null. + public static Dictionary XamlTypeList = new Dictionary() { + {typeof(System.Xaml.Replacements.TypeExtension),null}, + {typeof(String),null}, + {typeof(Int32),null}, + {typeof(Boolean),null}, + {typeof(Double), null}, + {typeof(Reference),null}, + }; + + } + + internal static class XmlDirectives + { + public const string Uri = "http://www.w3.org/XML/1998/namespace"; + public static ReadOnlyCollection NamespaceList = new ReadOnlyCollection(new Collection() { XmlDirectives.Uri }); + public const string xml_Space = "space"; + public const string xml_Lang = "lang"; + public const string xml_Base = "base"; + + public static DirectiveInfo[] DirectiveInfoTable = new DirectiveInfo[] { + new DirectivePropertyInfo(xml_Space, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.Attribute, XmlDirectives.NamespaceList), + + new DirectivePropertyInfo(xml_Lang, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.Attribute, XmlDirectives.NamespaceList), + + // xml:base appears in the NodeStream but never in XML text. + new DirectivePropertyInfo(xml_Base, typeof(string), XamlTextSyntax.StringSyntax, + AllowedMemberLocation.None, XmlDirectives.NamespaceList), + }; + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XamlPropertyInfoKey.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XamlPropertyInfoKey.cs new file mode 100644 index 00000000000..156c08b999e --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XamlPropertyInfoKey.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +using System.Windows.Markup; + +#if SILVERLIGHTXAML +using MS.Internal.Xaml.Schema; +using MS.Internal.Xaml; +#else +using System.Xaml.Schema; +using System.Xaml; +#endif + +#if SILVERLIGHTXAML +namespace MS.Internal.Xaml.MS.Impl +#else +namespace System.Xaml.MS.Impl +#endif +{ + enum XamlImplMemberKind { None, Property, Attachable, Event }; + + class XamlMemberInfoKey + { + XamlImplMemberKind _kind; + + MemberInfo _memberInfo1; + MemberInfo _memberInfo2; + int _hashCode = 0; + + public XamlMemberInfoKey(PropertyInfo pi) + { + _kind = XamlImplMemberKind.Property; + _memberInfo1 = pi; + } + + public XamlMemberInfoKey(MethodInfo miGetter, MethodInfo miSetter) + { + _kind = XamlImplMemberKind.Attachable; + _memberInfo1 = miGetter; + _memberInfo2 = miSetter; + } + + public XamlMemberInfoKey(EventInfo ei) + { + _kind = XamlImplMemberKind.Event; + _memberInfo1 = ei; + } + + public XamlImplMemberKind Kind { get { return _kind; } } + public PropertyInfo PropertyInfo { get { return (PropertyInfo)_memberInfo1; } } + public EventInfo EventInfo { get { return (EventInfo)_memberInfo1; } } + public MethodInfo GetterMethodInfo { get { return (MethodInfo)_memberInfo1; } } + public MethodInfo SetterMethodInfo { get { return (MethodInfo)_memberInfo2; } } + + public override int GetHashCode() + { + if (_hashCode != 0) + { + return _hashCode; + } + _hashCode = (_memberInfo1 != null) + ? HashCode(_memberInfo1) + : HashCode(_memberInfo2); + + if (_hashCode == 0) + { + _hashCode = 1; + } + return _hashCode; + } + + private static int HashCode(MemberInfo mi) + { + if (mi == null) + return 0; + return mi.Name.GetHashCode() + mi.DeclaringType.Name.GetHashCode(); + } + + public override bool Equals(object obj) + { + XamlMemberInfoKey other = obj as XamlMemberInfoKey; + if (Object.ReferenceEquals(other, null)) + { + return false; + } + return (this._memberInfo1.DeclaringType == this._memberInfo1.DeclaringType) + && (this._memberInfo1.Name == other._memberInfo1.Name); + } + + public static bool operator ==(XamlMemberInfoKey xipi0, XamlMemberInfoKey xipi1) + { + return xipi0.Equals(xipi1); + } + + public static bool operator !=(XamlMemberInfoKey xipi0, XamlMemberInfoKey xipi1) + { + return !(xipi0 == xipi1); + } + } +} + diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XmlNsInfo.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XmlNsInfo.cs new file mode 100644 index 00000000000..3642d624a40 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XmlNsInfo.cs @@ -0,0 +1,570 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Xaml.Schema; +using System.Windows.Markup; +using System.Runtime.CompilerServices; +using System.Text; + +namespace System.Xaml.MS.Impl +{ + class XmlNsInfo + { + // Thread-safety: any lazily initalized fields in this class must be assigned idempotently. + // I.e. never assign until the result is complete; and if multiple threads are assigning + // at the same time, the results should be equivalent. + + // This property will always be non-null, unless the assembly is a collectible dynamic + // assembly, and gets unloaded. + internal Assembly Assembly { get { return (Assembly)_assembly.Target; } } + + private IList _nsDefs; + internal IList NsDefs + { + get + { + if (_nsDefs == null) + { + _nsDefs = LoadNsDefs(); + } + return _nsDefs; + } + } + + // Note this, is the only dictionary that we synchronize, because XamlSchemaContext adds to it + private ConcurrentDictionary> _clrToXmlNs = null; + internal ConcurrentDictionary> ClrToXmlNs + { + get + { + if (_clrToXmlNs == null) + { + _clrToXmlNs = LoadClrToXmlNs(); + } + return _clrToXmlNs; + } + } + + private ICollection _internalsVisibleTo; + internal ICollection InternalsVisibleTo + { + get + { + if (_internalsVisibleTo == null) + { + _internalsVisibleTo = LoadInternalsVisibleTo(); + } + return _internalsVisibleTo; + } + } + + private Dictionary _oldToNewNs = null; + internal Dictionary OldToNewNs + { + get + { + if (_oldToNewNs == null) + { + _oldToNewNs = LoadOldToNewNs(); + } + return _oldToNewNs; + } + } + + private Dictionary _prefixes = null; + internal Dictionary Prefixes + { + get + { + if (_prefixes == null) + { + _prefixes = LoadPrefixes(); + } + return _prefixes; + } + } + + private string _rootNamespace = null; + internal string RootNamespace + { + get + { + if (_rootNamespace == null) + { + _rootNamespace = LoadRootNamespace() ?? string.Empty; + } + return _rootNamespace; + } + } + + private WeakReference _assembly; + private IList _attributeData; + private bool _fullyQualifyAssemblyName; + + internal XmlNsInfo(Assembly assembly, bool fullyQualifyAssemblyName) + { + _assembly = new WeakReference(assembly); + _fullyQualifyAssemblyName = fullyQualifyAssemblyName; + } + + void EnsureReflectionOnlyAttributeData() + { + if (_attributeData == null) + { + // We don't scoop RefOnly assemblies out of the AppDomain; they'll always be rooted + // in XamlSchemaContext._referenceAssemblies or _xmlnsInfoForUnreferencedAssemblies. + // So they should never be collected. + Debug.Assert(Assembly != null, "RefOnly assemblies shouldn't be GCed"); + _attributeData = Assembly.GetCustomAttributesData(); + } + } + + internal static string GetPreferredPrefix(string prefix1, string prefix2) + { + if (prefix1.Length < prefix2.Length) + { + return prefix1; + } + else if (prefix2.Length < prefix1.Length) + { + return prefix2; + } + else if (StringComparer.Ordinal.Compare(prefix1, prefix2) < 0) + { + return prefix1; + } + return prefix2; + } + + IList LoadNsDefs() + { + IList result = new List(); + + Assembly assembly = Assembly; + if (assembly == null) + { + return result; + } + if (assembly.ReflectionOnly) + { + EnsureReflectionOnlyAttributeData(); + foreach (var cad in _attributeData) + { + if (LooseTypeExtensions.AssemblyQualifiedNameEquals(cad.Constructor.DeclaringType, typeof(XmlnsDefinitionAttribute))) + { + // WPF 3.0 ignores XmlnsDefinitionAttribute.AssemblyName, and so do we + string xmlns = cad.ConstructorArguments[0].Value as string; + string clrns = cad.ConstructorArguments[1].Value as string; + LoadNsDefHelper(result, xmlns, clrns, assembly); + } + } + } + else + { + Attribute[] attributes; + attributes = Attribute.GetCustomAttributes(assembly, typeof(XmlnsDefinitionAttribute)); + foreach (Attribute attr in attributes) + { + XmlnsDefinitionAttribute xmlnsDefAttr = (XmlnsDefinitionAttribute)attr; + + string xmlns = xmlnsDefAttr.XmlNamespace; + string clrns = xmlnsDefAttr.ClrNamespace; + LoadNsDefHelper(result, xmlns, clrns, assembly); + } + } + return result; + } + + void LoadNsDefHelper(IList result, string xmlns, string clrns, Assembly assembly) + { + if (String.IsNullOrEmpty(xmlns) || clrns == null) + { + throw new XamlSchemaException(SR.Get(SRID.BadXmlnsDefinition, assembly.FullName)); + } + + result.Add(new XmlNsDefinition { ClrNamespace = clrns, XmlNamespace = xmlns }); + } + + ConcurrentDictionary> LoadClrToXmlNs() + { + ConcurrentDictionary> result = + XamlSchemaContext.CreateDictionary>(); + + Assembly assembly = Assembly; + if (assembly == null) + { + return result; + } + foreach (XmlNsDefinition nsDef in NsDefs) + { + IList xmlNamespaceList; + if (!result.TryGetValue(nsDef.ClrNamespace, out xmlNamespaceList)) + { + xmlNamespaceList = new List(); + result.TryAdd(nsDef.ClrNamespace, xmlNamespaceList); + } + xmlNamespaceList.Add(nsDef.XmlNamespace); + } + + string assemblyName = _fullyQualifyAssemblyName ? + assembly.FullName : XamlSchemaContext.GetAssemblyShortName(assembly); + foreach (KeyValuePair> clrToXmlNs in result) + { + // Sort namespaces in preference order + List nsList = (List)clrToXmlNs.Value; + NamespaceComparer comparer = new NamespaceComparer(this, assembly); + nsList.Sort(comparer.CompareNamespacesByPreference); + // Add clr-namespace form as last choice + string clrNsUri = ClrNamespaceUriParser.GetUri(clrToXmlNs.Key, assemblyName); + nsList.Add(clrNsUri); + } + // Convert to read-only lists so we can safely return these from public API + MakeListsImmutable(result); + return result; + } + + ICollection LoadInternalsVisibleTo() + { + var result = new List(); + + Assembly assembly = Assembly; + if (assembly == null) + { + return result; + } + if (assembly.ReflectionOnly) + { + EnsureReflectionOnlyAttributeData(); + foreach (var cad in _attributeData) + { + if (LooseTypeExtensions.AssemblyQualifiedNameEquals(cad.Constructor.DeclaringType, typeof(InternalsVisibleToAttribute))) + { + string assemblyName = cad.ConstructorArguments[0].Value as string; + LoadInternalsVisibleToHelper(result, assemblyName, assembly); + } + } + } + else + { + Attribute[] attributes = Attribute.GetCustomAttributes(assembly, typeof(InternalsVisibleToAttribute)); + for (int i = 0; i < attributes.Length; i++) + { + InternalsVisibleToAttribute ivAttrib = (InternalsVisibleToAttribute)attributes[i]; + LoadInternalsVisibleToHelper(result, ivAttrib.AssemblyName, assembly); + } + } + return result; + } + + void LoadInternalsVisibleToHelper(List result, string assemblyName, Assembly assembly) + { + if (assemblyName == null) + { + throw new XamlSchemaException(SR.Get(SRID.BadInternalsVisibleTo1, assembly.FullName)); + } + try + { + result.Add(new AssemblyName(assemblyName)); + } + catch (ArgumentException ex) + { + throw new XamlSchemaException(SR.Get(SRID.BadInternalsVisibleTo2, assemblyName, assembly.FullName), ex); + } + // AssemblyName.ctor throws FLE on malformed assembly name + catch (FileLoadException ex) + { + throw new XamlSchemaException(SR.Get(SRID.BadInternalsVisibleTo2, assemblyName, assembly.FullName), ex); + } + } + + Dictionary LoadOldToNewNs() + { + Dictionary result = new Dictionary(StringComparer.Ordinal); + + Assembly assembly = Assembly; + if (assembly == null) + { + return result; + } + if (assembly.ReflectionOnly) + { + EnsureReflectionOnlyAttributeData(); + + foreach (var cad in _attributeData) + { + if (LooseTypeExtensions.AssemblyQualifiedNameEquals(cad.Constructor.DeclaringType, typeof(XmlnsCompatibleWithAttribute))) + { + string oldns = cad.ConstructorArguments[0].Value as string; + string newns = cad.ConstructorArguments[1].Value as string; + LoadOldToNewNsHelper(result, oldns, newns, assembly); + } + } + } + else + { + Attribute[] attributes = Attribute.GetCustomAttributes(assembly, typeof(XmlnsCompatibleWithAttribute)); + foreach (Attribute attr in attributes) + { + // Read in the attribute value + XmlnsCompatibleWithAttribute xmlnsCompatAttr = (XmlnsCompatibleWithAttribute)attr; + LoadOldToNewNsHelper(result, xmlnsCompatAttr.OldNamespace, xmlnsCompatAttr.NewNamespace, assembly); + } + } + + return result; + } + + void LoadOldToNewNsHelper(Dictionary result, string oldns, string newns, Assembly assembly) + { + if (String.IsNullOrEmpty(newns) || String.IsNullOrEmpty(oldns)) + { + throw new XamlSchemaException(SR.Get(SRID.BadXmlnsCompat, assembly.FullName)); + } + + if (result.ContainsKey(oldns)) + { + throw new XamlSchemaException(SR.Get(SRID.DuplicateXmlnsCompat, assembly.FullName, oldns)); + } + result.Add(oldns, newns); + } + + Dictionary LoadPrefixes() + { + Dictionary result = new Dictionary(StringComparer.Ordinal); + + Assembly assembly = Assembly; + if (assembly == null) + { + return result; + } + if (assembly.ReflectionOnly) + { + EnsureReflectionOnlyAttributeData(); + + foreach (var cad in _attributeData) + { + if (LooseTypeExtensions.AssemblyQualifiedNameEquals(cad.Constructor.DeclaringType, typeof(XmlnsPrefixAttribute))) + { + string xmlns = cad.ConstructorArguments[0].Value as string; + string prefix = cad.ConstructorArguments[1].Value as string; + LoadPrefixesHelper(result, xmlns, prefix, assembly); + } + } + } + else + { + Attribute[] attributes = Attribute.GetCustomAttributes(assembly, typeof(XmlnsPrefixAttribute)); + foreach (Attribute attr in attributes) + { + XmlnsPrefixAttribute xmlnsPrefixAttr = (XmlnsPrefixAttribute)attr; + LoadPrefixesHelper(result, xmlnsPrefixAttr.XmlNamespace, xmlnsPrefixAttr.Prefix, assembly); + } + } + return result; + } + + void LoadPrefixesHelper(Dictionary result, string xmlns, string prefix, Assembly assembly) + { + if (String.IsNullOrEmpty(prefix) || String.IsNullOrEmpty(xmlns)) + { + throw new XamlSchemaException(SR.Get(SRID.BadXmlnsPrefix, assembly.FullName)); + } + + string oldPrefix; + if (!result.TryGetValue(xmlns, out oldPrefix) || + GetPreferredPrefix(oldPrefix, prefix) == prefix) + { + result[xmlns] = prefix; + } + } + + string LoadRootNamespace() + { + Assembly assembly = Assembly; + if (assembly == null) + { + return null; + } + if (assembly.ReflectionOnly) + { + EnsureReflectionOnlyAttributeData(); + + foreach (var cad in _attributeData) + { + if (LooseTypeExtensions.AssemblyQualifiedNameEquals(cad.Constructor.DeclaringType, typeof(RootNamespaceAttribute))) + { + return cad.ConstructorArguments[0].Value as string; + } + } + return null; + } + else + { + RootNamespaceAttribute rootNs = (RootNamespaceAttribute) + Attribute.GetCustomAttribute(assembly, typeof(RootNamespaceAttribute)); + return (rootNs == null) ? null : rootNs.Namespace; + } + } + + void MakeListsImmutable(IDictionary> dict) + { + // Need to copy the keys because we can't change a dictionary while iterating + string[] keys = new string[dict.Count]; + dict.Keys.CopyTo(keys, 0); + foreach (string key in keys) + { + dict[key] = new ReadOnlyCollection(dict[key]); + } + + } + + private class NamespaceComparer + { + XmlNsInfo _nsInfo; + IDictionary _subsumeCount; + + public NamespaceComparer(XmlNsInfo nsInfo, Assembly assembly) + { + _nsInfo = nsInfo; + + // Calculate the subsume count upfront, since this also serves as our cycle detection + _subsumeCount = new Dictionary(nsInfo.OldToNewNs.Count); + + Dictionary visited = new Dictionary(); + + // for every XmlnsCompatAtribute + foreach (string newNs in nsInfo.OldToNewNs.Values) + { + visited.Clear(); + + // Increment the subsume count for all transitive subsumers + string ns = newNs; + do + { + if (visited.ContainsKey(ns)) + { + throw new XamlSchemaException(SR.Get(SRID.XmlnsCompatCycle, assembly.FullName, ns)); + } + visited.Add(ns, null); + IncrementSubsumeCount(ns); + ns = GetNewNs(ns); + } + while (ns != null); + } + } + + public int CompareNamespacesByPreference(string ns1, string ns2) + { + if (KS.Eq(ns1, ns2)) + { + return 0; + } + const int Prefer_NS1 = -1; + const int Prefer_NS2 = 1; + + // If one namespace subsumes the other, favor the subsumer + string newNs = GetNewNs(ns1); + while (newNs != null) + { + if (newNs == ns2) + { + return Prefer_NS2; + } + newNs = GetNewNs(newNs); + } + newNs = GetNewNs(ns2); + while (newNs != null) + { + if (newNs == ns1) + { + return Prefer_NS1; + } + newNs = GetNewNs(newNs); + } + + // Favor namespaces that aren't subsumed over ones that are + if (GetNewNs(ns1) == null) + { + if (GetNewNs(ns2) != null) + { + return Prefer_NS1; + } + } + else if (GetNewNs(ns2) == null) + { + return Prefer_NS2; + } + + // Favor namespaces that subsume a greater number of other namespaces + int ns1count = 0, ns2count = 0; + _subsumeCount.TryGetValue(ns1, out ns1count); + _subsumeCount.TryGetValue(ns2, out ns2count); + if (ns1count > ns2count) + { + return Prefer_NS1; + } + else if (ns2count > ns1count) + { + return Prefer_NS2; + } + + // Favor namespaces with prefixes over namespaces without prefixes + // Favor namespaces with shorter prefixes over namespaces with longer ones + string prefix1, prefix2; + _nsInfo.Prefixes.TryGetValue(ns1, out prefix1); + _nsInfo.Prefixes.TryGetValue(ns2, out prefix2); + if (string.IsNullOrEmpty(prefix1)) + { + if (!string.IsNullOrEmpty(prefix2)) + { + return Prefer_NS2; + } + } + else if (string.IsNullOrEmpty(prefix2)) + { + return Prefer_NS1; + } + else if (prefix1.Length < prefix2.Length) + { + return Prefer_NS1; + } + else if (prefix2.Length < prefix1.Length) + { + return Prefer_NS2; + } + + // fall back to ordinal comparison + return StringComparer.Ordinal.Compare(ns1, ns2); + } + + private string GetNewNs(string oldNs) + { + string newNs; + _nsInfo.OldToNewNs.TryGetValue(oldNs, out newNs); + return newNs; + } + + private void IncrementSubsumeCount(string ns) + { + int currentCount; + _subsumeCount.TryGetValue(ns, out currentCount); + currentCount++; + _subsumeCount[ns] = currentCount; + } + } + + internal class XmlNsDefinition + { + public string ClrNamespace { get; set; } + public string XmlNamespace { get; set; } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/NameReferenceConverter.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/NameReferenceConverter.cs new file mode 100644 index 00000000000..edef5faf68a --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/NameReferenceConverter.cs @@ -0,0 +1,85 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Xaml; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel; +using System.Globalization; + +namespace System.Windows.Markup +{ + public class NameReferenceConverter: TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + { + return true; + } + + return base.CanConvertFrom(context, sourceType); + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (context == null) + { + throw new ArgumentNullException("context"); + } + + var nameResolver = (IXamlNameResolver)context.GetService(typeof(IXamlNameResolver)); + if (nameResolver == null) + { + throw new InvalidOperationException(SR.Get(SRID.MissingNameResolver)); + } + + string name = value as string; + if (String.IsNullOrEmpty(name)) + { + throw new InvalidOperationException(SR.Get(SRID.MustHaveName)); + } + object obj = nameResolver.Resolve(name); + if (obj == null) + { + string[] names = new string[] { name }; + obj = nameResolver.GetFixupToken(names, true); + } + return obj; + } + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (context == null || (context.GetService(typeof(IXamlNameProvider)) as IXamlNameProvider) == null) + { + return false; + } + + if (destinationType == typeof(string)) + { + return true; + } + + return base.CanConvertTo(context, destinationType); + + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + if (context == null) + { + throw new ArgumentNullException("context"); + } + + var nameProvider = (IXamlNameProvider)context.GetService(typeof(IXamlNameProvider)); + if (nameProvider == null) + { + throw new InvalidOperationException(SR.Get(SRID.MissingNameProvider)); + } + + return nameProvider.GetName(value); + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/NameScopeDictionary.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/NameScopeDictionary.cs new file mode 100644 index 00000000000..d1e2c2e5d35 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/NameScopeDictionary.cs @@ -0,0 +1,346 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Xaml +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Collections.Specialized; + using System.Xaml.MS.Impl; + using System.Windows.Markup; + + // + // The implementation for this class is taken directly from the source of NameScope, including the use + // of HybridDictionary to match the performance semantics of 3.0 for the time being + // Note that the IEnumerable uses KeyValuePair + // This means that we need to create KeyValuePairs on the fly + // The other option would be to just use IEnumerable (or change the HybridDictionary to Dictionary) + // but I opted for generic usability for now since this shouldn't be a common hot path. + internal class NameScopeDictionary : INameScopeDictionary + { + private HybridDictionary _nameMap; + private INameScope _underlyingNameScope; + private FrugalObjectList _names; + + public NameScopeDictionary() + { + } + + public NameScopeDictionary(INameScope underlyingNameScope) + { + if (underlyingNameScope == null) + { + throw new ArgumentNullException("underlyingNameScope"); + } + + _names = new FrugalObjectList(); + _underlyingNameScope = underlyingNameScope; + } + + public void RegisterName(string name, object scopedElement) + { + if (name == null) + throw new ArgumentNullException("name"); + + if (scopedElement == null) + throw new ArgumentNullException("scopedElement"); + + if (name == String.Empty) + throw new ArgumentException(SR.Get(SRID.NameScopeNameNotEmptyString)); + + if (!NameValidationHelper.IsValidIdentifierName(name)) + { + throw new ArgumentException(SR.Get(SRID.NameScopeInvalidIdentifierName, name)); + } + + if (_underlyingNameScope != null) + { + _names.Add(name); + _underlyingNameScope.RegisterName(name, scopedElement); + } + else + { + if (_nameMap == null) + { + _nameMap = new HybridDictionary(); + _nameMap[name] = scopedElement; + } + else + { + object nameContext = _nameMap[name]; + + if (nameContext == null) + { + _nameMap[name] = scopedElement; + } + else if (scopedElement != nameContext) + { + throw new ArgumentException(SR.Get(SRID.NameScopeDuplicateNamesNotAllowed, name)); + } + } + } + } + + public void UnregisterName(string name) + { + if (name == null) + throw new ArgumentNullException("name"); + + if (name == String.Empty) + throw new ArgumentException(SR.Get(SRID.NameScopeNameNotEmptyString)); + + if (_underlyingNameScope != null) + { + _underlyingNameScope.UnregisterName(name); + _names.Remove(name); + } + else + { + if (_nameMap != null && _nameMap[name] != null) + { + _nameMap.Remove(name); + } + else + { + throw new ArgumentException(SR.Get(SRID.NameScopeNameNotFound, name)); + } + } + } + + public object FindName(string name) + { + if (name == null) + throw new ArgumentNullException("name"); + + if (name == String.Empty) + throw new ArgumentException(SR.Get(SRID.NameScopeNameNotEmptyString)); + + if (_underlyingNameScope != null) + { + return _underlyingNameScope.FindName(name); + } + else + { + if (_nameMap == null) + { + return null; + } + return _nameMap[name]; + } + } + + internal INameScope UnderlyingNameScope { get { return _underlyingNameScope; } } + + class Enumerator : IEnumerator> + { + int index; + IDictionaryEnumerator dictionaryEnumerator; + HybridDictionary _nameMap; + INameScope _underlyingNameScope; + FrugalObjectList _names; + + public Enumerator(NameScopeDictionary nameScopeDictionary) + { + _nameMap = nameScopeDictionary._nameMap; + _underlyingNameScope = nameScopeDictionary._underlyingNameScope; + _names = nameScopeDictionary._names; + + if (_underlyingNameScope != null) + { + index = -1; + } + else + { + if (_nameMap != null) + { + dictionaryEnumerator = _nameMap.GetEnumerator(); + } + } + } + + public void Dispose() + { + GC.SuppressFinalize(this); + } + + public KeyValuePair Current + { + get + { + if (_underlyingNameScope != null) + { + string name = _names[index]; + return new KeyValuePair(name, _underlyingNameScope.FindName(name)); + } + else + { + if (_nameMap != null) + { + return new KeyValuePair((string)dictionaryEnumerator.Key, dictionaryEnumerator.Value); + } + + return default(KeyValuePair); + } + } + } + + public bool MoveNext() + { + if (_underlyingNameScope != null) + { + if (index == _names.Count - 1) + { + return false; + } + + index++; + return true; + } + else + { + if (_nameMap != null) + { + return dictionaryEnumerator.MoveNext(); + } + + return false; + } + } + + object IEnumerator.Current + { + get + { + return this.Current; + } + } + + void IEnumerator.Reset() + { + if (_underlyingNameScope != null) + { + index = -1; + } + else + { + dictionaryEnumerator.Reset(); + } + } + } + + IEnumerator> GetEnumerator() + { + return new Enumerator(this); + } + + #region IEnumerable methods + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + #endregion + + #region IEnumerable methods + IEnumerator> IEnumerable>.GetEnumerator() + { + return new Enumerator(this); + } + #endregion + + #region ICollection methods + int ICollection>.Count + { + get + { + throw new NotImplementedException(); + } + } + + bool ICollection>.IsReadOnly + { + get + { + throw new NotImplementedException(); + } + } + + void ICollection>.Clear() + { + throw new NotImplementedException(); + } + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + bool ICollection>.Remove(KeyValuePair item) + { + throw new NotImplementedException(); + } + + void ICollection>.Add(KeyValuePair item) + { + throw new NotImplementedException(); + } + + bool ICollection>.Contains(KeyValuePair item) + { + throw new NotImplementedException(); + } + + #endregion + + #region IDictionary methods + object IDictionary.this[string key] + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + void IDictionary.Add(string key, object value) + { + throw new NotImplementedException(); + } + + bool IDictionary.ContainsKey(string key) + { + throw new NotImplementedException(); + } + + bool IDictionary.Remove(string key) + { + throw new NotImplementedException(); + } + + bool IDictionary.TryGetValue(string key, out object value) + { + throw new NotImplementedException(); + } + + ICollection IDictionary.Keys + { + get + { + throw new NotImplementedException(); + } + } + + ICollection IDictionary.Values + { + get + { + throw new NotImplementedException(); + } + } + #endregion + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/NamespaceDeclaration.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/NamespaceDeclaration.cs new file mode 100644 index 00000000000..af964c42bab --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/NamespaceDeclaration.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; + +namespace System.Xaml +{ + [DebuggerDisplay("Prefix={Prefix} Namespace={Namespace}")] + public class NamespaceDeclaration + { + private string prefix; + + private string ns; + + public NamespaceDeclaration(string ns, string prefix) + { + this.ns = ns; + this.prefix = prefix; + } + + public string Prefix + { + get + { + return prefix; + } + } + + public string Namespace + { + get + { + return ns; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/ObjectReaderSettings.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/ObjectReaderSettings.cs new file mode 100644 index 00000000000..7362ae3ee1f --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/ObjectReaderSettings.cs @@ -0,0 +1,6 @@ +namespace System.Xaml +{ + public class ObjectReaderSettings : XamlReaderSettings + { + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/GenericTypeNameParser.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/GenericTypeNameParser.cs new file mode 100644 index 00000000000..d7a96e787b2 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/GenericTypeNameParser.cs @@ -0,0 +1,339 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Xaml; +using System.Xaml.Schema; +using System.Diagnostics; +using System.Runtime.Serialization; + +namespace MS.Internal.Xaml.Parser +{ + class GenericTypeNameParser + { + [Serializable] + class TypeNameParserException : Exception + { + public TypeNameParserException(string message) + : base(message) + { + } + + protected TypeNameParserException(SerializationInfo si, StreamingContext sc) : base(si, sc) + { + } + } + + private GenericTypeNameScanner _scanner; + private string _inputText; + private Func _prefixResolver; + Stack _stack; + + public GenericTypeNameParser(Func prefixResolver) + { + _prefixResolver = prefixResolver; + } + + public static XamlTypeName ParseIfTrivalName(string text, Func prefixResolver, out string error) + { + int parenIdx = text.IndexOf('('); + int bracketIdx = text.IndexOf('['); + if (parenIdx != -1 || bracketIdx != -1) + { + error = String.Empty; + return null; + } + + string prefix; + string simpleName; + + error = String.Empty; + if (!XamlQualifiedName.Parse(text, out prefix, out simpleName)) + { + error = SR.Get(SRID.InvalidTypeString, text); + return null; + } + + string ns = prefixResolver(prefix); + if (String.IsNullOrEmpty(ns)) + { + error = SR.Get(SRID.PrefixNotFound, prefix); + return null; + } + XamlTypeName xamlTypeName = new XamlTypeName(ns, simpleName); + return xamlTypeName; + } + + public XamlTypeName ParseName(string text, out string error) + { + error = String.Empty; + _scanner = new GenericTypeNameScanner(text); + _inputText = text; + + StartStack(); + + try + { + _scanner.Read(); + P_XamlTypeName(); + if (_scanner.Token != GenericTypeNameScannerToken.NONE) + { + ThrowOnBadInput(); + } + } + catch (TypeNameParserException ex) + { + error = ex.Message; + } + + XamlTypeName typeName = null; + if (String.IsNullOrEmpty(error)) + { + typeName = CollectNameFromStack(); + } + return typeName; + } + + public IList ParseList(string text, out string error) + { + _scanner = new GenericTypeNameScanner(text); + _inputText = text; + StartStack(); + + error = String.Empty; + try + { + _scanner.Read(); + P_XamlTypeNameList(); + if (_scanner.Token != GenericTypeNameScannerToken.NONE) + { + ThrowOnBadInput(); + } + } + catch (TypeNameParserException ex) + { + error = ex.Message; + } + + IList typeNameList = null; + if (String.IsNullOrEmpty(error)) + { + typeNameList = CollectNameListFromStack(); + } + return typeNameList; + } + + // XamlTypeName ::= SimpleTypeName TypeParameters? Subscript* + // SimpleTypeName ::= (Prefix ‘:’)? TypeName + // TypeParameters ::= ‘(‘ XamlTypeNameList ‘)’ + // XamlTypeNameList ::= XamlTypeName NameListExt* + // NameListExt ::= ‘,’ XamlTypeName + // Subscript ::= ‘[’ ‘,’* ‘]’ + + // XamlTypeName ::= SimpleTypeName TypeParameters? Subscript* + // + private void P_XamlTypeName() + { + // Required + if (_scanner.Token != GenericTypeNameScannerToken.NAME) + { + ThrowOnBadInput(); + } + P_SimpleTypeName(); + + // Optional + if (_scanner.Token == GenericTypeNameScannerToken.OPEN) + { + P_TypeParameters(); + } + + // Optional + if (_scanner.Token == GenericTypeNameScannerToken.SUBSCRIPT) + { + P_RepeatingSubscript(); + } + + Callout_EndOfType(); + } + + + // SimpleTypeName ::= (Prefix ‘:’)? TypeName + // + private void P_SimpleTypeName() + { + // caller checks this. + Debug.Assert(_scanner.Token == GenericTypeNameScannerToken.NAME); + + string prefix = String.Empty; + string name = _scanner.MultiCharTokenText; + _scanner.Read(); + + // Colon is optional. + if (_scanner.Token == GenericTypeNameScannerToken.COLON) + { + prefix = name; + _scanner.Read(); + + // IF there was a colon then there must be a name following. + if (_scanner.Token != GenericTypeNameScannerToken.NAME) + { + ThrowOnBadInput(); + } + name = _scanner.MultiCharTokenText; + _scanner.Read(); + + } + Callout_FoundName(prefix, name); + } + + // TypeParameters ::= ‘(‘ XamlTypeNameList ‘)’ + // + private void P_TypeParameters() + { + // Required + // caller checks this. + Debug.Assert(_scanner.Token == GenericTypeNameScannerToken.OPEN); + _scanner.Read(); + + P_XamlTypeNameList(); + + // Required + if (_scanner.Token != GenericTypeNameScannerToken.CLOSE) + { + ThrowOnBadInput(); + } + _scanner.Read(); + } + + // XamlTypeNameList ::= XamlTypeName NameListExt* + // + private void P_XamlTypeNameList() + { + P_XamlTypeName(); + + // optional zero or more. + while (_scanner.Token == GenericTypeNameScannerToken.COMMA) + { + P_NameListExt(); + } + } + + // NameListExt ::= ‘,’ XamlTypeName + // + private void P_NameListExt() + { + // Caller checked this. + Debug.Assert(_scanner.Token == GenericTypeNameScannerToken.COMMA); + _scanner.Read(); + + P_XamlTypeName(); + } + + // Subscript ::= ‘[’ ‘,’* ‘]’ + // + private void P_RepeatingSubscript() + { + // caller checks this. + Debug.Assert(_scanner.Token == GenericTypeNameScannerToken.SUBSCRIPT); + + do + { + Callout_Subscript(_scanner.MultiCharTokenText); + _scanner.Read(); + } + while (_scanner.Token == GenericTypeNameScannerToken.SUBSCRIPT); + } + + private void ThrowOnBadInput() + { + throw new TypeNameParserException(SR.Get(SRID.InvalidCharInTypeName, _scanner.ErrorCurrentChar, _inputText)); + } + + private void StartStack() + { + _stack = new Stack(); + TypeNameFrame frame; + frame = new TypeNameFrame(); + _stack.Push(frame); + } + + void Callout_FoundName(string prefix, string name) + { + TypeNameFrame frame = new TypeNameFrame(); + frame.Name = name; + string ns = _prefixResolver(prefix); + if (ns == null) + { + throw new TypeNameParserException(SR.Get(SRID.PrefixNotFound, prefix)); + } + frame.Namespace = ns; + _stack.Push(frame); + } + + void Callout_EndOfType() + { + TypeNameFrame frame = _stack.Pop(); + XamlTypeName typeName = new XamlTypeName(frame.Namespace, frame.Name, frame.TypeArgs); + + frame = _stack.Peek(); + if (frame.TypeArgs == null) + { + frame.AllocateTypeArgs(); + } + frame.TypeArgs.Add(typeName); + } + + void Callout_Subscript(string subscript) + { + TypeNameFrame frame = _stack.Peek(); + frame.Name += subscript; + } + + private XamlTypeName CollectNameFromStack() + { + if (_stack.Count != 1) + { + throw new TypeNameParserException(SR.Get(SRID.InvalidTypeString, _inputText)); + } + + TypeNameFrame frame = _stack.Peek(); + if (frame.TypeArgs.Count != 1) + { + throw new TypeNameParserException(SR.Get(SRID.InvalidTypeString, _inputText)); + } + + XamlTypeName xamlTypeName = frame.TypeArgs[0]; + return xamlTypeName; + } + + private IList CollectNameListFromStack() + { + if (_stack.Count != 1) + { + throw new TypeNameParserException(SR.Get(SRID.InvalidTypeString, _inputText)); + } + + TypeNameFrame frame = _stack.Peek(); + + List xamlTypeNameList = frame.TypeArgs; + return xamlTypeNameList; + } + } + + class TypeNameFrame + { + List _typeArgs; + + public string Namespace { get; set; } + public string Name { get; set; } + public List TypeArgs { get { return _typeArgs; } } + + public void AllocateTypeArgs() + { + _typeArgs = new List(); + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/GenericTypeNameScanner.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/GenericTypeNameScanner.cs new file mode 100644 index 00000000000..bcfb32fb415 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/GenericTypeNameScanner.cs @@ -0,0 +1,385 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; + +using System.Xaml.MS.Impl; + +namespace MS.Internal.Xaml.Parser +{ + internal enum GenericTypeNameScannerToken { NONE, ERROR, OPEN, CLOSE, COLON, COMMA, SUBSCRIPT, NAME } + + internal class GenericTypeNameScanner : Sample_StringParserBase + { + internal enum State { START, INNAME, INSUBSCRIPT } + + public const char Space = ' '; + public const char OpenParen = '('; + public const char CloseParen = ')'; + public const char Comma = ','; + public const char OpenBracket = '['; + public const char CloseBracket = ']'; + public const char Colon = ':'; + + private GenericTypeNameScannerToken _token; + private string _tokenText; + private State _state; + private GenericTypeNameScannerToken _pushedBackSymbol; + private int _multiCharTokenStartIdx; + private int _multiCharTokenLength; + private char _lastChar; + + public GenericTypeNameScanner(string text) + :base(text) + { + _state = State.START; + _pushedBackSymbol = GenericTypeNameScannerToken.NONE; + } + + public GenericTypeNameScannerToken Token { get { return _token; } } + + public string MultiCharTokenText { get { return _tokenText; } } + + public char ErrorCurrentChar { get { return _lastChar; } } + + public void Read() + { + if (_pushedBackSymbol != GenericTypeNameScannerToken.NONE) + { + _token = _pushedBackSymbol; + _pushedBackSymbol = GenericTypeNameScannerToken.NONE; + return; + } + + _token = GenericTypeNameScannerToken.NONE; + _tokenText = String.Empty; + _multiCharTokenStartIdx = -1; + _multiCharTokenLength = 0; + + while (_token == GenericTypeNameScannerToken.NONE) + { + if(IsAtEndOfInput) + { + if (_state == State.INNAME) + { + _token = GenericTypeNameScannerToken.NAME; + _state = State.START; + } + if (_state == State.INSUBSCRIPT) + { + _token = GenericTypeNameScannerToken.ERROR; + _state = State.START; + } + break; + } + + switch (_state) + { + case State.START: + State_Start(); + break; + + case State.INNAME: + State_InName(); + break; + + case State.INSUBSCRIPT: + State_InSubscript(); + break; + } + } + if (_token == GenericTypeNameScannerToken.NAME || _token == GenericTypeNameScannerToken.SUBSCRIPT) + { + _tokenText = CollectMultiCharToken(); + } + } + + // Parse a single subscript (e.g. [] or [,]) at the given position, returning its rank + // Returns 0 if the parse failed + internal static int ParseSubscriptSegment(string subscript, ref int pos) + { + bool openBracketFound = false; + int rank = 1; + do + { + switch (subscript[pos]) + { + case OpenBracket: + if (openBracketFound) + { + return 0; + } + openBracketFound = true; + break; + case Comma: + if (!openBracketFound) + { + return 0; + } + rank++; + break; + case CloseBracket: + if (!openBracketFound) + { + return 0; + } + pos++; + return rank; + default: + // Whitespace is allowed inside subscripts + if (!IsWhitespaceChar(subscript[pos])) + { + return 0; + } + break; + } + pos++; + } + while (pos < subscript.Length); + //unterminated string + return 0; + } + + // strips the subscript off the end of typeName, and returns it + internal static string StripSubscript(string typeName, out string subscript) + { + int openBracketNdx = typeName.IndexOf(GenericTypeNameScanner.OpenBracket); + if (openBracketNdx < 0) + { + subscript = null; + return typeName; + } + subscript = typeName.Substring(openBracketNdx); + return typeName.Substring(0, openBracketNdx); + } + + private void State_Start() + { + AdvanceOverWhitespace(); + if (IsAtEndOfInput) + { + _token = GenericTypeNameScannerToken.NONE; + return; + } + + switch (CurrentChar) + { + case OpenParen: + _token = GenericTypeNameScannerToken.OPEN; + break; + + case CloseParen: + _token = GenericTypeNameScannerToken.CLOSE; + break; + + case Comma: + _token = GenericTypeNameScannerToken.COMMA; + break; + + case Colon: + _token = GenericTypeNameScannerToken.COLON; + break; + + case OpenBracket: + StartMultiCharToken(); + _state = State.INSUBSCRIPT; + // No _token set so continue to scan. + break; + + default: + if(XamlName.IsValidNameStartChar(CurrentChar)) + { + StartMultiCharToken(); + _state = State.INNAME; + // No _token set so continue to scan. + } + else + { + _token = GenericTypeNameScannerToken.ERROR; + } + break; + } + _lastChar = CurrentChar; + Advance(); + } + + private void State_InName() + { + if(IsAtEndOfInput || IsWhitespaceChar(CurrentChar) || CurrentChar == OpenBracket) + { + _token = GenericTypeNameScannerToken.NAME; + _state = State.START; + return; + } + + switch(CurrentChar) + { + case OpenParen: + _pushedBackSymbol = GenericTypeNameScannerToken.OPEN; + _token = GenericTypeNameScannerToken.NAME; + _state = State.START; + break; + + case CloseParen: + _pushedBackSymbol = GenericTypeNameScannerToken.CLOSE; + _token = GenericTypeNameScannerToken.NAME; + _state = State.START; + break; + + case Comma: + _pushedBackSymbol = GenericTypeNameScannerToken.COMMA; + _token = GenericTypeNameScannerToken.NAME; + _state = State.START; + break; + + case Colon: + _pushedBackSymbol = GenericTypeNameScannerToken.COLON; + _token = GenericTypeNameScannerToken.NAME; + _state = State.START; + break; + + default: + if (XamlName.IsValidQualifiedNameChar(CurrentChar)) + { + AddToMultiCharToken(); + // No _token set so continue to scan. + } + else + { + _token = GenericTypeNameScannerToken.ERROR; + } + break; + } + _lastChar = CurrentChar; + Advance(); + } + + private void State_InSubscript() + { + if (IsAtEndOfInput) + { + _token = GenericTypeNameScannerToken.ERROR; + _state = State.START; + return; + } + + switch (CurrentChar) + { + case Comma: + AddToMultiCharToken(); + break; + + case CloseBracket: + AddToMultiCharToken(); + _token = GenericTypeNameScannerToken.SUBSCRIPT; + _state = State.START; + break; + + default: + if (IsWhitespaceChar(CurrentChar)) + { + AddToMultiCharToken(); + } + else + { + _token = GenericTypeNameScannerToken.ERROR; + } + break; + } + _lastChar = CurrentChar; + Advance(); + } + + private void StartMultiCharToken() + { + Debug.Assert(_multiCharTokenStartIdx == -1 && _multiCharTokenLength == 0); + + _multiCharTokenStartIdx = _idx; + _multiCharTokenLength = 1; + } + + private void AddToMultiCharToken() + { + Debug.Assert(_multiCharTokenStartIdx != -1 && _multiCharTokenLength > 0); + + _multiCharTokenLength += 1; + } + + private string CollectMultiCharToken() + { + if (_multiCharTokenStartIdx == 0 && _multiCharTokenLength == _inputText.Length) + { + return _inputText; + } + string result = _inputText.Substring(_multiCharTokenStartIdx, _multiCharTokenLength); + return result; + } + } + + + internal class Sample_StringParserBase + { + protected const char NullChar = '\0'; + + protected String _inputText; + protected int _idx; + + public Sample_StringParserBase(string text) + { + _inputText = text; + _idx = 0; + } + + protected char CurrentChar + { + get { return _inputText[_idx]; } + } + + public bool IsAtEndOfInput + { + get { return (_idx >= _inputText.Length); } + } + + protected bool Advance() + { + ++_idx; + if (IsAtEndOfInput) + { + _idx = _inputText.Length; + return false; + } + return true; + } + + protected static bool IsWhitespaceChar(char ch) + { + Debug.Assert(KnownStrings.WhitespaceChars.Length == 5); + + if (ch == KnownStrings.WhitespaceChars[0] || + ch == KnownStrings.WhitespaceChars[1] || + ch == KnownStrings.WhitespaceChars[2] || + ch == KnownStrings.WhitespaceChars[3] || + ch == KnownStrings.WhitespaceChars[4]) + { + return true; + } + return false; + } + + protected bool AdvanceOverWhitespace() + { + bool sawWhitespace = true; + + while (!IsAtEndOfInput && IsWhitespaceChar(CurrentChar)) + { + sawWhitespace = true; + Advance(); + } + return sawWhitespace; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/MePullParser.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/MePullParser.cs new file mode 100644 index 00000000000..51aad3a3a83 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/MePullParser.cs @@ -0,0 +1,514 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Xaml; +using System.Diagnostics; +using MS.Internal.Xaml.Context; +using System.Xaml.Schema; +using System.Xaml.MS.Impl; + +namespace MS.Internal.Xaml.Parser +{ + internal class MePullParser + { + XamlParserContext _context; + string _originalText; + MeScanner _tokenizer; + string _brokenRule; + + [DebuggerDisplay("{found}")] + private class Found + { + public bool found; + } + + public MePullParser(XamlParserContext stack) + { + _context = stack; + } + + // MarkupExtension ::= '{' TYPENAME Arguments? '}' + // Arguments ::= (PositionalArgs ( ',' NamedArgs)?) | NamedArgs + // NamedArgs ::= NamedArg ( ',' NamedArg )* + // NamedArg ::= PROPERTYNAME '=' (STRING | QUOTEDMARKUPEXTENSION | MarkupExtension) + // PositionalArgs ::= (Value (',' PositionalArgs)?) | NamedArg + // Value ::= STRING | QUOTEDMARKUPEXTENSION |MarkupExtension + + public IEnumerable Parse(string text, int lineNumber, int linePosition) + { + _tokenizer = new MeScanner(_context, text, lineNumber, linePosition); + _originalText = text; + Found f = new Found(); + NextToken(); + foreach (XamlNode node in P_MarkupExtension(f)) + { + yield return node; + } + if (!f.found) + { + string brokenRule = _brokenRule; + _brokenRule = null; + throw new XamlParseException(_tokenizer, brokenRule); + } + if (_tokenizer.Token != MeTokenType.None) + { + throw new XamlParseException(_tokenizer, SR.Get(SRID.UnexpectedTokenAfterME)); + } + if (_tokenizer.HasTrailingWhitespace) + { + throw new XamlParseException(_tokenizer, SR.Get(SRID.WhitespaceAfterME)); + } + } + + private void SetBrokenRuleString(string ruleString) + { + if (String.IsNullOrEmpty(_brokenRule)) + { + _brokenRule = SR.Get(SRID.UnexpectedToken, + _tokenizer.Token, ruleString, _originalText); + } + } + + private bool Expect(MeTokenType token, string ruleString) + { + if(_tokenizer.Token != token) + { + SetBrokenRuleString(ruleString); + return false; + } + return true; + } + + //////////////////////////////// + // MarkupExtension ::= '{' TYPENAME Arguments? '}' + // + private IEnumerable P_MarkupExtension(Found f) + { + // MarkupExtension ::= @'{' TYPENAME Arguments? '}' + if (Expect(MeTokenType.Open, "MarkupExtension ::= @'{' Expr '}'")) + { + NextToken(); + + // MarkupExtension ::= '{' @TYPENAME Arguments? '}' + if (_tokenizer.Token == MeTokenType.TypeName) + { + XamlType xamlType = _tokenizer.TokenType; + + yield return Logic_StartElement(xamlType, _tokenizer.Namespace); + + NextToken(); + + // MarkupExtension ::= '{' TYPENAME @(Arguments)? '}' + Found f2 = new Found(); + switch (_tokenizer.Token) + { + // MarkupExtension ::= '{' TYPENAME (Arguments)? @'}' + case MeTokenType.Close: // legal, Arguments is optional + yield return Logic_EndObject(); + NextToken(); + f.found = true; + break; + + case MeTokenType.String: + case MeTokenType.QuotedMarkupExtension: + case MeTokenType.PropertyName: + case MeTokenType.Open: + // MarkupExtension ::= '{' TYPENAME (@Arguments)? '}' + foreach (XamlNode node in P_Arguments(f2)) + { + yield return node; + } + break; + + default: + SetBrokenRuleString("MarkupExtension ::= '{' TYPENAME @(Arguments)? '}'"); + break; + } + + if (f2.found) + { + if (Expect(MeTokenType.Close, "MarkupExtension ::= '{' TYPENAME (Arguments)? @'}'")) + { + yield return Logic_EndObject(); + f.found = true; + NextToken(); + } + } + } + else + { + SetBrokenRuleString("MarkupExtension ::= '{' @TYPENAME (Arguments)? '}'"); + } + } + } + + //////////////////////////////// + // Arguments ::= (PositionalArgs ( ',' NamedArgs)?) | NamedArgs + // + private IEnumerable P_Arguments(Found f) + { + Found f2 = new Found(); + // Arguments ::= @ (PositionalArgs ( ',' NamedArgs)?) | NamedArgs + switch (_tokenizer.Token) + { + case MeTokenType.Close: // not found + break; + + // Arguments ::= (@ PositionalArgs ( ',' NamedArgs)?) | NamedArgs + case MeTokenType.String: + case MeTokenType.QuotedMarkupExtension: + case MeTokenType.Open: + foreach (XamlNode node in P_PositionalArgs(f2)) + { + yield return node; + } + f.found = f2.found; + if (f.found) + { + if (_context.CurrentArgCount > 0) + { + yield return Logic_EndPositionalParameters(); + } + } + + // Arguments ::= (PositionalArgs @ ( ',' NamedArgs)?) | NamedArgs + while (_tokenizer.Token == MeTokenType.Comma) + { + // Arguments ::= (PositionalArgs ( @ ',' NamedArgs)?) | NamedArgs + NextToken(); + + // Arguments ::= (PositionalArgs ( ',' @ NamedArgs)?) | NamedArgs + foreach (XamlNode node in P_NamedArgs(f2)) + { + yield return node; + } + } + break; + + // Arguments ::= (PositionalArgs ( ',' NamedArgs)?) | @ NamedArgs + case MeTokenType.PropertyName: + foreach (XamlNode node in P_NamedArgs(f2)) + { + yield return node; + } + f.found = f2.found; + break; + + default: + SetBrokenRuleString("Arguments ::= @ (PositionalArgs ( ',' NamedArgs)?) | NamedArgs"); + break; + } + } + + //////////////////////////////// + // PositionalArgs ::= (Value (',' PositionalArgs)?) | NamedArg + // + private IEnumerable P_PositionalArgs(Found f) + { + Found f2 = new Found(); + + // PositionalArgs ::= @ (Value (',' PositionalArgs)?) | NamedArg + switch (_tokenizer.Token) + { + // PositionalArgs ::= ( @ Value (',' PositionalArgs)?) | NamedArg + case MeTokenType.String: + case MeTokenType.QuotedMarkupExtension: + case MeTokenType.Open: + if (_context.CurrentArgCount++ == 0) + { + yield return Logic_StartPositionalParameters(); + } + + foreach (XamlNode node in P_Value(f2)) + { + yield return node; + } + if (!f2.found) + { + SetBrokenRuleString("PositionalArgs ::= (NamedArg | (@Value (',' PositionalArgs)?)"); + break; + } + f.found = f2.found; + + // PositionalArgs ::= (Value @ (',' PositionalArgs)?) | NamedArg + if (_tokenizer.Token == MeTokenType.Comma) + { + Found f3 = new Found(); + + // PositionalArgs ::= (Value ( @ ',' PositionalArgs)?) | NamedArg + NextToken(); + + // PositionalArgs ::= (Value (',' @ PositionalArgs)?) | NamedArg + foreach (XamlNode node in P_PositionalArgs(f3)) + { + yield return node; + } + if (!f3.found) + { + SetBrokenRuleString("PositionalArgs ::= (Value (',' @ PositionalArgs)?) | NamedArg"); + break; + } + // no f.found this is optional + } + break; + + // PositionalArgs ::= (Value (',' PositionalArgs)?) | @ NamedArg + case MeTokenType.PropertyName: + if (_context.CurrentArgCount > 0) + { + yield return Logic_EndPositionalParameters(); + } + foreach (XamlNode node in P_NamedArg(f2)) + { + yield return node; + } + if (!f2.found) + { + SetBrokenRuleString("PositionalArgs ::= (Value (',' PositionalArgs)?) | @ NamedArg"); + } + f.found = f2.found; + break; + + default: + SetBrokenRuleString("PositionalArgs ::= @ (Value (',' PositionalArgs)?) | NamedArg"); + break; + } + } + + //////////////////////////////// + // NamedArgs ::= NamedArg ( ',' NamedArg )* + // + private IEnumerable P_NamedArgs(Found f) + { + Found f2 = new Found(); + + // NamedArgs ::= @NamedArg ( ',' NamedArg )* + switch (_tokenizer.Token) + { + case MeTokenType.PropertyName: + foreach (XamlNode node in P_NamedArg(f2)) + { + yield return node; + } + f.found = f2.found; + + // NamedArgs ::= NamedArg @( ',' NamedArg )* + while (_tokenizer.Token == MeTokenType.Comma) + { + // NamedArgs ::= NamedArg ( @',' NamedArg )* + NextToken(); + + // NamedArgs ::= NamedArg ( ',' @NamedArg )* + foreach (XamlNode node in P_NamedArg(f2)) + { + yield return node; + } + } + break; + + default: + SetBrokenRuleString("NamedArgs ::= @NamedArg ( ',' NamedArg )*"); + break; + } + } + + //////////////////////////////// + // Value ::= (STRING | QUOTEDMARKUPEXTENSION | MarkupExtension) + // + private IEnumerable P_Value(Found f) + { + Found f2 = new Found(); + + // Value ::= @(STRING | QUOTEDMARKUPEXTENSION | MarkupExtension) + switch (_tokenizer.Token) + { + // Value ::= (@STRING | QUOTEDMARKUPEXTENSION | MarkupExtension) + case MeTokenType.String: + yield return Logic_Text(); + f.found = true; + NextToken(); + break; + + // Value ::= (STRING | @QUOTEDMARKUPEXTENSION | MarkupExtension) + case MeTokenType.QuotedMarkupExtension: + MePullParser nestedParser = new MePullParser(_context); + foreach (XamlNode node in nestedParser.Parse(_tokenizer.TokenText, LineNumber, LinePosition)) + { + yield return node; + } + f.found = true; + NextToken(); + break; + + // Value ::= (STRING | QUOTEDMARKUPEXTENSION | @MarkupExtension) + case MeTokenType.Open: + foreach (XamlNode node in P_MarkupExtension(f2)) + { + yield return node; + } + f.found = f2.found; + break; + + default: + break; + } + } + + //////////////////////////////// + // NamedArg ::= PROPERTYNAME '=' (STRING | QUOTEDMARKUPEXTENSION | MarkupExtension) + // + private IEnumerable P_NamedArg(Found f) + { + Found f2 = new Found(); + + // NamedArg ::= @PROPERTYNAME '=' (STRING | QUOTEDMARKUPEXTENSION | MarkupExtension) + if (_tokenizer.Token == MeTokenType.PropertyName) + { + XamlMember property = _tokenizer.TokenProperty; + yield return Logic_StartMember(); + NextToken(); + + // NamedArg ::= PROPERTYNAME @'=' (STRING | QUOTEDMARKUPEXTENSION | MarkupExtension) + Expect(MeTokenType.EqualSign, "NamedArg ::= PROPERTYNAME @'=' Value"); + NextToken(); + + // NamedArg ::= PROPERTYNAME '=' @(STRING | QUOTEDMARKUPEXTENSION | MarkupExtension) + switch (_tokenizer.Token) + { + // NamedArg ::= PROPERTYNAME '=' (@STRING | QUOTEDMARKUPEXTENSION | MarkupExtension) + case MeTokenType.String: + yield return Logic_Text(); + f.found = true; + NextToken(); + break; + + // NamedArg ::= PROPERTYNAME '=' (STRING | @QUOTEDMARKUPEXTENSION | MarkupExtension) + case MeTokenType.QuotedMarkupExtension: + MePullParser nestedParser = new MePullParser(_context); + foreach (XamlNode node in nestedParser.Parse(_tokenizer.TokenText, LineNumber, LinePosition)) + { + yield return node; + } + f.found = true; + NextToken(); + break; + + // NamedArg ::= PROPERTYNAME '=' (STRING | QUOTEDMARKUPEXTENSION | @MarkupExtension) + case MeTokenType.Open: + foreach (XamlNode node in P_Value(f2)) + { + yield return node; + } + f.found = f2.found; + break; + + case MeTokenType.PropertyName: + { + string error; + if (_context.CurrentMember == null) + { + error = SR.Get(SRID.MissingComma1, _tokenizer.TokenText); + } + else + { + error = SR.Get(SRID.MissingComma2, _context.CurrentMember.Name, _tokenizer.TokenText); + } + throw new XamlParseException(_tokenizer, error); + } + + default: + SetBrokenRuleString("NamedArg ::= PROPERTYNAME '=' @(STRING | QUOTEDMARKUPEXTENSION | MarkupExtension)"); + break; + } + yield return Logic_EndMember(); + } + } + + + // ================================================ + + private void NextToken() + { + _tokenizer.Read(); + } + + private int LineNumber + { + get { return _tokenizer.LineNumber; } + } + + + private int LinePosition + { + get { return _tokenizer.LinePosition; } + } + + // ================================================ + + private XamlNode Logic_StartElement(XamlType xamlType, string xamlNamespace) + { + _context.PushScope(); + _context.CurrentType = xamlType; + _context.CurrentTypeNamespace = xamlNamespace; + + _context.InitLongestConstructor(xamlType); + _context.InitBracketCharacterCacheForType(xamlType); + _context.CurrentBracketModeParseParameters = new BracketModeParseParameters(_context); + + var startObj = new XamlNode(XamlNodeType.StartObject, xamlType); + return startObj; + } + + private XamlNode Logic_EndObject() + { + _context.PopScope(); + return new XamlNode(XamlNodeType.EndObject); + } + + private XamlNode Logic_StartMember() + { + XamlMember member = _tokenizer.TokenProperty; + _context.CurrentMember = member; + + XamlNode startMember = new XamlNode(XamlNodeType.StartMember, member); + return startMember; + } + + private XamlNode Logic_EndMember() + { + _context.CurrentMember = null; + return new XamlNode(XamlNodeType.EndMember); + } + + private XamlNode Logic_StartPositionalParameters() + { + _context.CurrentMember = XamlLanguage.PositionalParameters; + + XamlNode startProperty = new XamlNode(XamlNodeType.StartMember, XamlLanguage.PositionalParameters); + return startProperty; + } + + private XamlNode Logic_EndPositionalParameters() + { + // the Ctor args were pushed onto the Builder (XamlWriter) + // stack, but were not pushed onto the parser stack, so the + // ME is still the CurrentType for us. + + XamlType xamlType = _context.CurrentType; + + _context.CurrentArgCount = 0; + _context.CurrentMember = null; + return new XamlNode(XamlNodeType.EndMember); + } + + private XamlNode Logic_Text() + { + string text = _tokenizer.TokenText; + XamlNode textNode = new XamlNode(XamlNodeType.Value, text); + return textNode; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/MeScanner.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/MeScanner.cs new file mode 100644 index 00000000000..22f0c9ea653 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/MeScanner.cs @@ -0,0 +1,638 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Text; +using System.Diagnostics; +using System.Xaml; +using MS.Internal.Xaml.Context; +using System.Xaml.Schema; +using System.Xaml.MS.Impl; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace MS.Internal.Xaml.Parser +{ + // Markup Extension Tokenizer AKA Scanner. + + enum MeTokenType + { + None, + Open = '{', + Close = '}', + EqualSign = '=', + Comma = ',', + TypeName, // String - Follows a '{' space delimited + PropertyName, // String - Preceeds a '='. {},= delimited, can (but shouldn't) contain spaces. + String, // String - all other strings, {},= delimited can contain spaces. + QuotedMarkupExtension // String - must be recursivly parsed as a MarkupExtension. + }; + + // 1) Value and (propertynames for compatibility with WPF 3.0) can also have + // escaped character with '\' to include '{' '}' ',' '=', and '\'. + // 2) Value strings can also be quoted (w/ ' or ") in their entirity to escape all + // uses of the above characters. + // 3) All strings are trimmed of whitespace front and back unless they were quoted. + // 4) Quote characters can only appear at the start and end of strings. + // 5) TypeNames cannot be quoted. + + internal class MeScanner + { + public const char Space = ' '; + public const char OpenCurlie = '{'; + public const char CloseCurlie = '}'; + public const char Comma = ','; + public const char EqualSign = '='; + public const char Quote1 = '\''; + public const char Quote2 = '\"'; + public const char Backslash = '\\'; + public const char NullChar = '\0'; + + enum StringState { Value, Type, Property }; + + XamlParserContext _context; + string _inputText; + int _idx; + MeTokenType _token; + XamlType _tokenXamlType; + XamlMember _tokenProperty; + string _tokenNamespace; + string _tokenText; + StringState _state; + bool _hasTrailingWhitespace; + int _lineNumber; + int _startPosition; + private string _currentParameterName; + private SpecialBracketCharacters _currentSpecialBracketCharacters; + + public MeScanner(XamlParserContext context, string text, int lineNumber, int linePosition) + { + _context = context; + _inputText = text; + _lineNumber = lineNumber; + _startPosition = linePosition; + _idx = -1; + _state = StringState.Value; + _currentParameterName = null; + _currentSpecialBracketCharacters = null; + } + + public int LineNumber + { + get { return _lineNumber; } + } + + public int LinePosition + { + get + { + int offset = (_idx < 0) ? 0 : _idx; + return _startPosition + offset; + } + } + + public string Namespace + { + get { return _tokenNamespace; } + } + + public MeTokenType Token + { + get { return _token; } + } + + public XamlType TokenType + { + get { return _tokenXamlType; } + } + + public XamlMember TokenProperty + { + get { return _tokenProperty; } + } + + // FxCop says this is never called + // (but _tokenNamespace is used internally in the Scanner) + //public XamlNamespace TokenNamespace + //{ + // get { return _tokenNamespace; } + //} + + public string TokenText + { + get { return _tokenText; } + } + + public bool IsAtEndOfInput + { + get { return (_idx >= _inputText.Length); } + } + + public bool HasTrailingWhitespace + { + get { return _hasTrailingWhitespace; } + } + + public void Read() + { + bool isQuotedMarkupExtension = false; + bool readString = false; + + _tokenText = String.Empty; + _tokenXamlType = null; + _tokenProperty = null; + _tokenNamespace = null; + + Advance(); + AdvanceOverWhitespace(); + + if (IsAtEndOfInput) + { + _token = MeTokenType.None; + return; + } + + switch (CurrentChar) + { + case OpenCurlie: + if (NextChar == CloseCurlie) // the {} escapes the ME. return the string. + { + _token = MeTokenType.String; + _state = StringState.Value; + readString = true; // ReadString() will strip the leading {} + } + else + { + _token = MeTokenType.Open; + _state = StringState.Type; // types follow '{' + } + break; + + case Quote1: + case Quote2: + if (NextChar == OpenCurlie) + { + Advance(); // read ahead one character + if (NextChar != CloseCurlie) // check for the '}' of a {} + { + isQuotedMarkupExtension = true; + } + PushBack(); // put back the read-ahead. + } + readString = true; // read substring" + break; + + case CloseCurlie: + _token = MeTokenType.Close; + _state = StringState.Value; + break; + + case EqualSign: + _token = MeTokenType.EqualSign; + _state = StringState.Value; + _context.CurrentBracketModeParseParameters.IsConstructorParsingMode = false; + break; + + case Comma: + _token = MeTokenType.Comma; + _state = StringState.Value; + if (_context.CurrentBracketModeParseParameters.IsConstructorParsingMode) + { + _context.CurrentBracketModeParseParameters.IsConstructorParsingMode = + ++_context.CurrentBracketModeParseParameters.CurrentConstructorParam < + _context.CurrentBracketModeParseParameters.MaxConstructorParams; + } + break; + + default: + readString = true; + break; + } + + if(readString) + { + if (_context.CurrentType.IsMarkupExtension + && _context.CurrentBracketModeParseParameters != null + && _context.CurrentBracketModeParseParameters.IsConstructorParsingMode) + { + int currentCtrParam = _context.CurrentBracketModeParseParameters.CurrentConstructorParam; + _currentParameterName = _context.CurrentLongestConstructorOfMarkupExtension[currentCtrParam].Name; + _currentSpecialBracketCharacters = GetBracketCharacterForProperty(_currentParameterName); + } + + string str = ReadString(); + _token = (isQuotedMarkupExtension) ? MeTokenType.QuotedMarkupExtension : MeTokenType.String; + + switch (_state) + { + case StringState.Value: + break; + + case StringState.Type: + _token = MeTokenType.TypeName; + ResolveTypeName(str); + break; + + case StringState.Property: + _token = MeTokenType.PropertyName; + ResolvePropertyName(str); + break; + } + _state = StringState.Value; + _tokenText = RemoveEscapes(str); + } + } + + private static string RemoveEscapes(string value) + { + if (value.StartsWith("{}", StringComparison.OrdinalIgnoreCase)) + { + value = value.Substring(2); + } + + if (!value.Contains("\\")) + { + return value; + } + + StringBuilder builder = new StringBuilder(value.Length); + int start = 0; + int idx; + do + { + idx = value.IndexOf(Backslash, start); + if (idx < 0) + { + builder.Append(value.Substring(start)); + break; + } + else + { + int clearTextLength = idx - start; + + // Copy Clear Text + builder.Append(value.Substring(start, clearTextLength)); + + // Add the character after the backslash + if (idx + 1 < value.Length) + { + builder.Append(value[idx + 1]); + } + + // pick up again after that + start = idx + 2; + } + } while (start < value.Length); + string result = builder.ToString(); + return result; + } + + private void ResolveTypeName(string longName) + { + string error; + XamlTypeName typeName = XamlTypeName.ParseInternal(longName, _context.FindNamespaceByPrefix, out error); + if (typeName == null) + { + throw new XamlParseException(this, error); + } + + // In curly form, we search for TypeName + 'Extension' before TypeName + string bareTypeName = typeName.Name; + typeName.Name = typeName.Name + KnownStrings.Extension; + XamlType xamlType = _context.GetXamlType(typeName, false); + // This would be cleaner if we moved the Extension fallback logic out of XSC + if (xamlType == null || + // Guard against Extension getting added twice + (xamlType.UnderlyingType != null && + KS.Eq(xamlType.UnderlyingType.Name, typeName.Name + KnownStrings.Extension))) + { + typeName.Name = bareTypeName; + xamlType = _context.GetXamlType(typeName, true); + } + + _tokenXamlType = xamlType; + _tokenNamespace = typeName.Namespace; + } + + private void ResolvePropertyName(string longName) + { + XamlPropertyName propName = XamlPropertyName.Parse(longName); + if (propName == null) + { + throw new ArgumentException(SR.Get(SRID.MalformedPropertyName)); + } + + XamlMember prop = null; + XamlType declaringType; + XamlType tagType = _context.CurrentType; + string tagNamespace = _context.CurrentTypeNamespace; + + if (propName.IsDotted) + { + prop = _context.GetDottedProperty(tagType, tagNamespace, propName, false /*tagIsRoot*/); + } + // Regular property p + else + { + // _tokenNamespace is always null here + string ns = _context.GetAttributeNamespace(propName, _tokenNamespace); + declaringType = _context.CurrentType; + + // _tokenNamespace is always null here + prop = _context.GetNoDotAttributeProperty(declaringType, propName, _tokenNamespace, ns, false /*tagIsRoot*/); + } + _tokenProperty = prop; + } + + private string ReadString() + { + bool escaped = false; + char quoteChar = NullChar; + bool atStart = true; + bool wasQuoted = false; + uint braceCount = 0; // To be compat with v3 which allowed balanced {} inside of strings + + StringBuilder sb = new StringBuilder(); + char ch; + + while(!IsAtEndOfInput) + { + ch = CurrentChar; + + // handle escaping and quoting first. + if(escaped) + { + sb.Append('\\'); + sb.Append(ch); + escaped = false; + } + else if (quoteChar != NullChar) + { + if (ch == Backslash) + { + escaped = true; + } + else if (ch != quoteChar) + { + sb.Append(ch); + } + else + { + ch = CurrentChar; + quoteChar = NullChar; + break; // we are done. + } + } + // If we are inside of MarkupExtensionBracketCharacters for a particular property or position parameter, + // scoop up everything inside one by one, and keep track of nested Bracket Characters in the stack. + else if (_context.CurrentBracketModeParseParameters != null && _context.CurrentBracketModeParseParameters.IsBracketEscapeMode) + { + Stack bracketCharacterStack = _context.CurrentBracketModeParseParameters.BracketCharacterStack; + if (_currentSpecialBracketCharacters.StartsEscapeSequence(ch)) + { + bracketCharacterStack.Push(ch); + } + else if (_currentSpecialBracketCharacters.EndsEscapeSequence(ch)) + { + if (_currentSpecialBracketCharacters.Match(bracketCharacterStack.Peek(), ch)) + { + bracketCharacterStack.Pop(); + } + else + { + throw new XamlParseException(this, SR.Get(SRID.InvalidClosingBracketCharacers, ch.ToString())); + } + } + else if (ch == MeScanner.Backslash) + { + escaped = true; + } + + if (bracketCharacterStack.Count == 0) + { + _context.CurrentBracketModeParseParameters.IsBracketEscapeMode = false; + } + + if (!escaped) + { + sb.Append(ch); + } + } + else + { + bool done = false; + switch (ch) + { + case Space: + if (_state == StringState.Type) + { + done = true; // we are done. + break; + } + sb.Append(ch); + break; + + case OpenCurlie: + braceCount++; + sb.Append(ch); + break; + case CloseCurlie: + if (braceCount == 0) + { + done = true; + } + else + { + braceCount--; + sb.Append(ch); + } + break; + case Comma: + done = true; // we are done. + break; + + case EqualSign: + _state = StringState.Property; + done = true; // we are done. + break; + + case Backslash: + escaped = true; + break; + + case Quote1: + case Quote2: + if (!atStart) + { + throw new XamlParseException(this, SR.Get(SRID.QuoteCharactersOutOfPlace)); + } + quoteChar = ch; + wasQuoted = true; + break; + + default: // All other character (including whitespace) + if (_currentSpecialBracketCharacters != null && _currentSpecialBracketCharacters.StartsEscapeSequence(ch)) + { + Stack bracketCharacterStack = + _context.CurrentBracketModeParseParameters.BracketCharacterStack; + bracketCharacterStack.Clear(); + bracketCharacterStack.Push(ch); + _context.CurrentBracketModeParseParameters.IsBracketEscapeMode = true; + } + + sb.Append(ch); + break; + } + + if (done) + { + if (braceCount > 0) + { + throw new XamlParseException(this, SR.Get(SRID.UnexpectedTokenAfterME)); + } + else + { + if (_context.CurrentBracketModeParseParameters?.BracketCharacterStack.Count > 0) + { + throw new XamlParseException(this, SR.Get(SRID.MalformedBracketCharacters, ch.ToString())); + } + } + + PushBack(); + break; // we are done. + } + } + atStart = false; + Advance(); + } + + if (quoteChar != NullChar) + { + throw new XamlParseException(this, SR.Get(SRID.UnclosedQuote)); + } + + string result = sb.ToString(); + if (!wasQuoted) + { + result = result.TrimEnd(KnownStrings.WhitespaceChars); + result = result.TrimStart(KnownStrings.WhitespaceChars); + } + + if (_state == StringState.Property) + { + _currentParameterName = result; + _currentSpecialBracketCharacters = GetBracketCharacterForProperty(_currentParameterName); + } + + return result; + } + + private char CurrentChar + { + get { return _inputText[_idx]; } + } + + private char NextChar + { + get + { + if (_idx + 1 < _inputText.Length) + { + return _inputText[_idx + 1]; + } + return NullChar; + } + } + + private bool Advance() + { + ++_idx; + if (IsAtEndOfInput) + { + _idx = _inputText.Length; + return false; + } + return true; + } + + private static bool IsWhitespaceChar(char ch) + { + Debug.Assert(KnownStrings.WhitespaceChars.Length == 5); + + if (ch == KnownStrings.WhitespaceChars[0] || + ch == KnownStrings.WhitespaceChars[1] || + ch == KnownStrings.WhitespaceChars[2] || + ch == KnownStrings.WhitespaceChars[3] || + ch == KnownStrings.WhitespaceChars[4]) + { + return true; + } + return false; + } + + private void AdvanceOverWhitespace() + { + bool sawWhitespace = false; + + while (!IsAtEndOfInput && IsWhitespaceChar(CurrentChar)) + { + sawWhitespace = true; + Advance(); + } + + // WFP 3.0 errors on trailing whitespace. + // [note: very first compat workaround in the new XAML parser] + // Noticing trailing whitespace is not very natural in this parser. + // so this extra code is here to implement this error. + if (IsAtEndOfInput && sawWhitespace) + { + _hasTrailingWhitespace = true; + } + } + + private void PushBack() + { + _idx -= 1; + } + + private SpecialBracketCharacters GetBracketCharacterForProperty(string propertyName) + { + SpecialBracketCharacters bracketCharacters = null; + if (_context.CurrentEscapeCharacterMapForMarkupExtension != null && + _context.CurrentEscapeCharacterMapForMarkupExtension.ContainsKey(propertyName)) + { + bracketCharacters = _context.CurrentEscapeCharacterMapForMarkupExtension[propertyName]; + } + + return bracketCharacters; + } + } + + internal class BracketModeParseParameters + { + internal BracketModeParseParameters(XamlParserContext context) + { + CurrentConstructorParam = 0; + IsBracketEscapeMode = false; + BracketCharacterStack = new Stack(); + if (context.CurrentLongestConstructorOfMarkupExtension != null) + { + IsConstructorParsingMode = context.CurrentLongestConstructorOfMarkupExtension.Length > 0; + MaxConstructorParams = context.CurrentLongestConstructorOfMarkupExtension.Length; + } + else + { + IsConstructorParsingMode = false; + MaxConstructorParams = 0; + } + } + + internal int CurrentConstructorParam { get; set; } + internal int MaxConstructorParams { get; set; } + internal bool IsConstructorParsingMode { get; set; } + internal bool IsBracketEscapeMode { get; set; } + internal Stack BracketCharacterStack { get; set; } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/NamespacePrefixLookup.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/NamespacePrefixLookup.cs new file mode 100644 index 00000000000..2b39fff6010 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/NamespacePrefixLookup.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Xaml; + +namespace MS.Internal.Xaml.Parser +{ + internal class NamespacePrefixLookup : INamespacePrefixLookup + { + private readonly List _newNamespaces; + private readonly Func _nsResolver; + public NamespacePrefixLookup(out IEnumerable newNamespaces, Func nsResolver) + { + newNamespaces = _newNamespaces = new List(); + _nsResolver = nsResolver; + } + + #region INamespacePrefixLookup Members + + private int n = 0; + public string LookupPrefix(string ns) + { + // we really shouldn't generate extraneous new namespaces + string newPrefix; + do { + newPrefix = "prefix" + n++; + } while (_nsResolver(newPrefix) != null); + _newNamespaces.Add(new NamespaceDeclaration(ns, newPrefix)); + return newPrefix; + } + + #endregion + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/NodeStreamSorter.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/NodeStreamSorter.cs new file mode 100644 index 00000000000..4d3e58ad513 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/NodeStreamSorter.cs @@ -0,0 +1,717 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Xaml.MS.Impl; +using System.Diagnostics; +using System.Xaml; +using MS.Internal.Xaml.Context; +using MS.Internal.Xaml.Parser; + +namespace MS.Internal.Xaml +{ + internal class NodeStreamSorter: IEnumerator + { + XamlParserContext _context; + XamlXmlReaderSettings _settings; + IEnumerator _source; + Queue _buffer; + XamlNode _current; + + ReorderInfo[] _sortingInfoArray; + XamlNode[] _originalNodesInOrder; + + Dictionary _xmlnsDictionary; + + class SeenCtorDirectiveFlags + { + public bool SeenInstancingProperty; + public bool SeenOutOfOrderCtorDirective; + } + + List _seenStack = new List(); + int _startObjectDepth = 0; + + List _moveList; + + private void InitializeObjectFrameStack() + { + if (_seenStack.Count == 0) + { + _seenStack.Add(new SeenCtorDirectiveFlags()); + } + _seenStack[0].SeenInstancingProperty = false; + _seenStack[0].SeenOutOfOrderCtorDirective = false; + } + + private void StartObjectFrame() + { + _startObjectDepth += 1; + if(_seenStack.Count <=_startObjectDepth) + { + _seenStack.Add(new SeenCtorDirectiveFlags()); + } + _seenStack[_startObjectDepth].SeenInstancingProperty = false; + _seenStack[_startObjectDepth].SeenOutOfOrderCtorDirective = false; + } + + private void EndObjectFrame() + { + _startObjectDepth -= 1; + } + + bool HaveSeenInstancingProperty + { + get { return _seenStack[_startObjectDepth].SeenInstancingProperty; } + set { _seenStack[_startObjectDepth].SeenInstancingProperty = value; } + } + + bool HaveSeenOutOfOrderCtorDirective + { + get { return _seenStack[_startObjectDepth].SeenOutOfOrderCtorDirective; } + set { _seenStack[_startObjectDepth].SeenOutOfOrderCtorDirective = value; } + } + + struct ReorderInfo + { + public int Depth { get; set; } + public int OriginalOrderIndex { get; set; } + public XamlNodeType XamlNodeType { get; set; } + +#if DEBUG + public override string ToString() + { + return String.Format(TypeConverterHelper.InvariantEnglishUS, "Depth[{0}] {2}", this.Depth, this.XamlNodeType); + } +#endif + } + + public NodeStreamSorter(XamlParserContext context, XamlPullParser parser, XamlXmlReaderSettings settings, Dictionary xmlnsDictionary) + { + _context = context; + _settings = settings; + _source = parser.Parse().GetEnumerator(); + _xmlnsDictionary = xmlnsDictionary; + + _buffer = new Queue(); + _sortingInfoArray = null; + + StartNewNodeStreamWithSettingsPreamble(); + ReadAheadAndSortCtorProperties(); + } + + #region IEnumerator Members + + public XamlNode Current + { + get { return _current; } + } + + object System.Collections.IEnumerator.Current + { + get { return _current; } + } + + public bool MoveNext() + { + do + { + if (_buffer.Count > 0) + { + _current = _buffer.Dequeue(); + } + else + { + if (!_source.MoveNext()) + { + return false; + } + _current = _source.Current; + if (_current.NodeType == XamlNodeType.StartObject) + { + // Out of order Ctor Directives could result in the Type of the Start Object + // being unresolved (UNKNOWN). So provide the SO in the buffer for possible fixup + // and then read the possibly fixed Start Object back after the Sort. + _buffer.Enqueue(_current); + ReadAheadAndSortCtorProperties(); + _current = _buffer.Dequeue(); + } + } + // Skip over "End Of Attributes" nodes. + } while (_current.IsEndOfAttributes); + return true; + } + + // required for the IEnumerable interface + // but not used in the parser's usage. + public void Reset() + { + throw new NotImplementedException(); + } + + // required for the IEnumerable interface + // but not used in the parser's usage. + // FxCop requires the call the SuppressFinalize(). + public void Dispose() + { + GC.SuppressFinalize(this); + } + + #endregion + + #region Preamble Methods + + // this does the initial load of the node stream buffer. + // It also looks at the XamlReaderSettings and inserts any XmlNs + // definitions and XML state required by the provided XamlReaderSettings. + private void StartNewNodeStreamWithSettingsPreamble() + { + XamlNode node; + bool foundFirstStartObject = false; + + while (!foundFirstStartObject) + { + _source.MoveNext(); + node = _source.Current; + switch (node.NodeType) + { + case XamlNodeType.NamespaceDeclaration: + _buffer.Enqueue(node); + break; + case XamlNodeType.StartObject: + foundFirstStartObject = true; + EnqueueInitialExtraXmlNses(); + _buffer.Enqueue(node); + EnqueueInitialXmlState(); + break; + case XamlNodeType.None: + if (node.IsLineInfo) + { + _buffer.Enqueue(node); + } + break; + default: + break; + } + } + } + + private void EnqueueInitialExtraXmlNses() + { + if (_xmlnsDictionary != null) + { + foreach (string prefix in _xmlnsDictionary.Keys) + { + // Skip any prefixes in the settings that were already defined + // in the XML text (on the root node) + if (_context.FindNamespaceByPrefixInParseStack(prefix) == null) + { + string uriString = _xmlnsDictionary[prefix]; + XamlNode node = new XamlNode(XamlNodeType.NamespaceDeclaration, new NamespaceDeclaration(uriString, prefix)); + _buffer.Enqueue(node); + } + } + } + } + + // Enqueue nodes from the "settings". + // I.e move state from the setting into the node stream. + private void EnqueueInitialXmlState() + { + string xmlNs = _context.FindNamespaceByPrefix(KnownStrings.XmlPrefix); + XamlSchemaContext schemaContext = _context.SchemaContext; + if (_settings.XmlSpacePreserve == true) + { + EnqueueOneXmlDirectiveProperty(XamlLanguage.Space, KnownStrings.Preserve); + } + if (!String.IsNullOrEmpty(_settings.XmlLang)) + { + EnqueueOneXmlDirectiveProperty(XamlLanguage.Lang, _settings.XmlLang); + } + if (_settings.BaseUri != null) + { + EnqueueOneXmlDirectiveProperty(XamlLanguage.Base, _settings.BaseUri.ToString()); + } + } + + private void EnqueueOneXmlDirectiveProperty(XamlMember xmlDirectiveProperty, string textValue) + { + var startProperty = new XamlNode(XamlNodeType.StartMember, xmlDirectiveProperty); + // No lineinfo for nodes that don't really appear in the text. + _buffer.Enqueue(startProperty); + + var textNode = new XamlNode(XamlNodeType.Value, textValue); + // No lineinfo for nodes that don't really appear in the text. + _buffer.Enqueue(textNode); + + // No lineinfo for nodes that don't really appear in the text. + _buffer.Enqueue(new XamlNode(XamlNodeType.EndMember)); + } + + #endregion + + // Read until we have all the attributes and the first directive property elements. + // We do this because some directive properties control Object creation and they + // can occur anywhere before the first property element. + // After we scoop all that up, reorder the Ctor directives to the front + // so the Builder(s) (aka Object Writer) have them right away. And don't + // have to look for them. + private void ReadAheadAndSortCtorProperties() + { + InitializeObjectFrameStack(); + _moveList = null; + + ReadAheadToEndObjectOrFirstPropertyElement(); + + // If we saw TypeArguments, Arguments, or FactoryMethod properties. + // then dig in and correct the stream. + // + //if (HaveSeenOutOfOrderCtorDirective) + if(_moveList != null) + { + SortContentsOfReadAheadBuffer(); + } + return; + } + + private void ReadAheadToEndObjectOrFirstPropertyElement() + { + ReadAheadToEndOfAttributes(); + ReadAheadToFirstInstancingProperty(); + } + + // This reads from immediatly after a start object and queues all the + // nodes to the end of the attributes. + // returns true if read End of Attributes. + // rerutns false if read End Object. + private void ReadAheadToEndOfAttributes() + { + XamlNode node; + int propertyDepth = 0; + bool done = false; + + do + { + if (!_source.MoveNext()) + { + throw new InvalidOperationException("premature end of stream before EoA"); + } + node = _source.Current; + switch (node.NodeType) + { + case XamlNodeType.StartObject: + StartObjectFrame(); + break; + + case XamlNodeType.EndObject: + EndObjectFrame(); + if (propertyDepth == 0) + { + done = true; + } + break; + + case XamlNodeType.None: + if (node.IsEndOfAttributes) + { + if (propertyDepth == 0) + { + done = true; + } + } + break; + + case XamlNodeType.StartMember: + { + propertyDepth += 1; + if (!HaveSeenOutOfOrderCtorDirective) + { + CheckForOutOfOrderCtorDirectives(node); + } + } + break; + + case XamlNodeType.EndMember: + propertyDepth -= 1; + break; + } + _buffer.Enqueue(node); + + } while (!done); + } + + // After the End of Attributes is found continue to buffer nodes + // until the first real property. Carefull there may be real objects + // with real properties inside of Directives. + private void ReadAheadToFirstInstancingProperty() + { + int propertyDepth = 0; + + bool done = false; + do + { + if (!_source.MoveNext()) + { + throw new InvalidOperationException("premature end of stream after EoA"); + } + XamlNode node = _source.Current; + switch (node.NodeType) + { + case XamlNodeType.StartMember: + { + propertyDepth++; + bool isInstancingProperty = CheckForOutOfOrderCtorDirectives(node); + if (isInstancingProperty && propertyDepth == 1) + { + done = true; + } + } + break; + + case XamlNodeType.EndMember: + propertyDepth--; + break; + + case XamlNodeType.EndObject: + if (propertyDepth == 0) + { + // end of current object, no real properties but we are done. + // Exit loop normaly so we Enqueue the EndObject. + done = true; + } + break; + } + _buffer.Enqueue(node); + } while (!done); + } + + // This updates the state of instancing vs. construction controling + // members. It also returns if the current member is "instancing or not". + private bool CheckForOutOfOrderCtorDirectives(XamlNode node) + { + XamlMember prop = node.Member; + bool isInstancingProperty = false; + if (IsCtorDirective(prop)) + { + if (HaveSeenInstancingProperty) + { + HaveSeenOutOfOrderCtorDirective = true; + if (_moveList == null) + { + _moveList = new List(); + } + _moveList.Add(_buffer.Count); // mark the current position as needing fixup + } + } + // Anything else except x:Key is an instancing member. + else if (!(prop.IsDirective && prop == XamlLanguage.Key)) + { + HaveSeenInstancingProperty = true; + isInstancingProperty = true; + } + return isInstancingProperty; + } + + private bool IsCtorDirective(XamlMember member) + { + if (!member.IsDirective) + { + return false; + } + if ((member == XamlLanguage.Initialization) + || (member == XamlLanguage.PositionalParameters) + || (member == XamlLanguage.FactoryMethod) + || (member == XamlLanguage.Arguments) + || (member == XamlLanguage.TypeArguments) + || (member == XamlLanguage.Base)) + { + return true; + } + return false; + } + + private bool IsInstancingMember(XamlMember member) + { + if (IsCtorDirective(member)) + { + return false; + } + if (member.IsDirective && member == XamlLanguage.Key) + { + return false; + } + // Actually... + // XamlLanguage.Uid, if the type has no UidProperty is not "instancing". + // But it might be slower to track the current type and lookup the UidProperty + // than to assume that Uid "might" be instancing. + return true; + } + + private void SortContentsOfReadAheadBuffer() + { + BuildSortingBuffer(); + + // Do the reordering + MoveList_Process(); + + // Load the result back in to the Buffer. + ReloadSortedBuffer(); + } + + private void BuildSortingBuffer() + { + _originalNodesInOrder = _buffer.ToArray(); + _buffer.Clear(); + + // Build an array with the info we need + _sortingInfoArray = new ReorderInfo[_originalNodesInOrder.Length]; + int depth = 0; + ReorderInfo rInfo = new ReorderInfo(); + + for (int i = 0; i < _originalNodesInOrder.Length; i++) + { + rInfo.Depth = depth; + rInfo.OriginalOrderIndex = i; + rInfo.XamlNodeType = _originalNodesInOrder[i].NodeType; + + switch (rInfo.XamlNodeType) + { + case XamlNodeType.NamespaceDeclaration: + case XamlNodeType.EndMember: + case XamlNodeType.Value: + break; + + case XamlNodeType.GetObject: + case XamlNodeType.StartObject: + rInfo.Depth = ++depth; + break; + + case XamlNodeType.EndObject: + rInfo.Depth = depth--; + break; + + case XamlNodeType.StartMember: + break; + } + _sortingInfoArray[i] = rInfo; + } + } + + private void ReloadSortedBuffer() + { + for (int idx = 0; idx < _sortingInfoArray.Length; idx++) + { + int xamlIndex = _sortingInfoArray[idx].OriginalOrderIndex; + _buffer.Enqueue(_originalNodesInOrder[xamlIndex]); + } + _sortingInfoArray = null; + } + + private void MoveList_Process() + { + int depth; + int ctorDirectiveIdx; + while (MoveList_RemoveStartMemberIndexWithGreatestDepth(out ctorDirectiveIdx, out depth)) + { + int startObjectIdx; + if (BackupTo(ctorDirectiveIdx, XamlNodeType.StartObject, depth, out startObjectIdx)) + { + int firstMemberIdx; + if (AdvanceTo(startObjectIdx, XamlNodeType.StartMember, depth, out firstMemberIdx)) + { + SortMembers(firstMemberIdx); + } + } + } + } + + private bool MoveList_RemoveStartMemberIndexWithGreatestDepth(out int deepestCtorIdx, out int deepestDepth) + { + deepestDepth = -1; + deepestCtorIdx = -1; + + int deepestIdx = -1; + if (_moveList.Count == 0) + { + return false; + } + for (int i = 0; i < _moveList.Count; i++) + { + int ctorIdx = _moveList[i]; + if (_sortingInfoArray[ctorIdx].Depth > deepestDepth) + { + deepestDepth = _sortingInfoArray[ctorIdx].Depth; + deepestCtorIdx = ctorIdx; + deepestIdx = i; + } + } + Debug.Assert(deepestIdx != -1); + _moveList.RemoveAt(deepestIdx); + return true; + } + + private void SortMembers(int start) + { + int depth = _sortingInfoArray[start].Depth; + Debug.Assert(_sortingInfoArray[start].XamlNodeType == XamlNodeType.StartMember); + + int idx = start; + while (idx < _sortingInfoArray.Length + && _sortingInfoArray[idx].XamlNodeType == XamlNodeType.StartMember) + { + int propIdx; + int ctorIdx; + if (!AdvanceToNextInstancingMember(idx, depth, out propIdx)) + { + break; + } + + if (!AdvanceToNextCtorDirective(propIdx, depth, out ctorIdx)) + { + break; + } + + int ctorDirectivesLength = AdvanceOverNoninstancingDirectives(ctorIdx, depth); + SwapRanges(propIdx, ctorIdx, ctorIdx + ctorDirectivesLength); + idx = ctorIdx + ctorDirectivesLength; + } + } + + private bool AdvanceToNextInstancingMember(int current, int depth, out int end) + { + Debug.Assert(_sortingInfoArray[current].XamlNodeType == XamlNodeType.StartMember); + + end = current; + int originalIdx = _sortingInfoArray[current].OriginalOrderIndex; + XamlMember nextMember = _originalNodesInOrder[originalIdx].Member; + while(!IsInstancingMember(nextMember)) + { + if(!AdvanceTo(current, XamlNodeType.StartMember, depth, out end)) + { + return false; + } + current = end; + originalIdx = _sortingInfoArray[current].OriginalOrderIndex; + nextMember = _originalNodesInOrder[originalIdx].Member; + }; + return true; + } + + private bool AdvanceToNextCtorDirective(int current, int depth, out int end) + { + Debug.Assert(_sortingInfoArray[current].XamlNodeType == XamlNodeType.StartMember); + + end = current; + int originalIdx = _sortingInfoArray[current].OriginalOrderIndex; + XamlMember member = _originalNodesInOrder[originalIdx].Member; + while (!IsCtorDirective(member)) + { + if (!AdvanceTo(current, XamlNodeType.StartMember, depth, out end)) + { + return false; + } + current = end; + originalIdx = _sortingInfoArray[current].OriginalOrderIndex; + member = _originalNodesInOrder[originalIdx].Member; + }; + return true; + } + + private int AdvanceOverNoninstancingDirectives(int start, int depth) + { + int current = start; + int end = current; + int originalIdx = _sortingInfoArray[current].OriginalOrderIndex; + XamlMember nextMember = _originalNodesInOrder[originalIdx].Member; + while (!IsInstancingMember(nextMember)) + { + if (!AdvanceTo(current, XamlNodeType.StartMember, depth, out end)) + { + if (AdvanceTo(current, XamlNodeType.EndObject, depth, out end)) + { + return end - start; + } + else + { + Debug.Assert(false, "Missing End Object in node sorter"); + } + } + current = end; + originalIdx = _sortingInfoArray[current].OriginalOrderIndex; + nextMember = _originalNodesInOrder[originalIdx].Member; + } + return end - start; + } + + private void SwapRanges(int beginning, int middle, int end) + { + int length1 = middle - beginning; + int length2 = end - middle; + Debug.Assert(length1 > 0 && length2 > 0); + + ReorderInfo[] temp = new ReorderInfo[length1]; + + // Copy first half into temp storage. + // srcArray, srcIdx, destArray, destIdx, length + Array.Copy(_sortingInfoArray, beginning, temp, 0, length1); + + // Copy second half up where the first half was. + // srcArray, srcIdx, destArray, destIdx, length + Array.Copy(_sortingInfoArray, middle, _sortingInfoArray, beginning, length2); + + // Copy first half out of temp storage in after the first half + // srcArray, srcIdx, destArray, destIdx, length + Array.Copy(temp, 0, _sortingInfoArray, beginning + length2, length1); + } + + private bool AdvanceTo(int start, XamlNodeType nodeType, int searchDepth, out int end) + { + for (int idx = start + 1; idx < _sortingInfoArray.Length; idx++) + { + XamlNodeType currentNodeType = _sortingInfoArray[idx].XamlNodeType; + int nodeDepth = _sortingInfoArray[idx].Depth; + if(nodeDepth == searchDepth) + { + if (currentNodeType == nodeType) + { + end = idx; + return true; + } + } + else if (nodeDepth < searchDepth) + { + end = idx; + return false; // we have searched past the end of the current Object. + } + } + end =_sortingInfoArray.Length; + return false; + } + + private bool BackupTo(int start, XamlNodeType nodeType, int searchDepth, out int end) + { + for (int idx = start - 1; idx >= 0; idx--) + { + XamlNodeType currentNodeType = _sortingInfoArray[idx].XamlNodeType; + int nodeDepth = _sortingInfoArray[idx].Depth; + if (nodeDepth == searchDepth) + { + if (currentNodeType == nodeType) + { + end = idx; + return true; + } + else if (nodeDepth < searchDepth) + { + end = idx; + return false; // we have searched past the start of the current Object. + } + } + } + end = 0; + return false; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/ScannerNodeType.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/ScannerNodeType.cs new file mode 100644 index 00000000000..7b8a10e7aa1 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/ScannerNodeType.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; + +namespace MS.Internal.Xaml.Parser +{ + internal enum ScannerNodeType + { + NONE, + ELEMENT, + EMPTYELEMENT, + ATTRIBUTE, + DIRECTIVE, + PREFIXDEFINITION, + PROPERTYELEMENT, + EMPTYPROPERTYELEMENT, + TEXT, + ENDTAG + }; + + internal enum ScannerAttributeKind + { + Namespace, + CtorDirective, + Name, + Directive, + XmlSpace, + Event, + Property, + AttachableProperty, + Unknown + }; +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlAttribute.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlAttribute.cs new file mode 100644 index 00000000000..2a8c9b8f3e7 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlAttribute.cs @@ -0,0 +1,178 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Xml; +using System.Xaml; +using MS.Internal.Xaml.Context; +using System.Xaml.MS.Impl; +using System.Xaml.Schema; + +namespace MS.Internal.Xaml.Parser +{ + [DebuggerDisplay("{Name.ScopedName}='{Value}' {Kind}")] + internal class XamlAttribute + { + private string _xmlnsDefinitionPrefix; // set only if it is a XmlNamespace + private string _xmlnsDefinitionUri; // set only if it is a XmlNamespace + + public XamlPropertyName Name { get; private set; } + public string Value { get; private set; } + public ScannerAttributeKind Kind { get; private set; } + public XamlMember Property { get; private set; } + public int LineNumber { get; private set; } + public int LinePosition { get; private set; } + + public XamlAttribute(XamlPropertyName propName, string val, IXmlLineInfo lineInfo) + { + Name = propName; + Value = val; + Kind = ScannerAttributeKind.Property; // non-"namespace" default; + if (lineInfo != null) + { + LineNumber = lineInfo.LineNumber; + LinePosition = lineInfo.LinePosition; + } + + // XmlNs like: xmlns:c="someUristring" + if (CheckIsXmlNamespaceDefinition(out _xmlnsDefinitionPrefix, out _xmlnsDefinitionUri)) + { + Kind = ScannerAttributeKind.Namespace; + } + } + + // This can only be done after the XmlNs's have be scanned and loaded + public void Initialize(XamlParserContext context, XamlType tagType, string ownerNamespace, bool tagIsRoot) + { + // Namespaces are already flagged (but not the other kinds). + if (Kind == ScannerAttributeKind.Namespace) + return; + + Property = GetXamlAttributeProperty(context, Name, tagType, ownerNamespace, tagIsRoot); + if (Property.IsUnknown) + { + Kind = ScannerAttributeKind.Unknown; + } + else if (Property.IsEvent) + { + Kind = ScannerAttributeKind.Event; + } + else if (Property.IsDirective) + { + if(Property == XamlLanguage.Space) + { + Kind = ScannerAttributeKind.XmlSpace; + } + else if ((Property == XamlLanguage.FactoryMethod) + || (Property == XamlLanguage.Arguments) + || (Property == XamlLanguage.TypeArguments) + || (Property == XamlLanguage.Base) + // || (Property == XamlLanguage.Initialization) // doesn't appear in Xml Text + // || (Property == XamlLanguage.PositionalParameters) // doesn't appear in Xml Text + ) + { + Kind = ScannerAttributeKind.CtorDirective; + } + else + { + Kind = ScannerAttributeKind.Directive; + } + } + else if(Property.IsAttachable) + { + Kind = ScannerAttributeKind.AttachableProperty; + } + else if (Property == tagType.GetAliasedProperty(XamlLanguage.Name)) + { + Kind = ScannerAttributeKind.Name; + } + else + { + Kind = ScannerAttributeKind.Property; + } + } + + + // FxCop says this is not called + //public bool IsXamlNsDefinition + //{ + // get { return (!String.IsNullOrEmpty(_xmlnsDefinitionUri)); } + //} + + // These properties are only defined if this Xml-Attribute is a XmlNs definition. + public string XmlNsPrefixDefined + { + get { return _xmlnsDefinitionPrefix; } + } + + public string XmlNsUriDefined + { + get { return _xmlnsDefinitionUri; } + } + + // ========================== internal ================================ + + internal bool CheckIsXmlNamespaceDefinition(out string definingPrefix, out string uri) + { + uri = String.Empty; + definingPrefix = String.Empty; + + // case where: xmlns:pre="ValueUri" + if (KS.Eq(Name.Prefix, KnownStrings.XmlNsPrefix)) + { + uri = Value; + definingPrefix = !Name.IsDotted + ? Name.Name + : Name.OwnerName + "." + Name.Name; + return true; + } + // case where: xmlns="ValueUri" + if (String.IsNullOrEmpty(Name.Prefix) && KS.Eq(Name.Name, KnownStrings.XmlNsPrefix)) + { + uri = Value; + definingPrefix = String.Empty; + return true; + } + return false; + } + + // ========================== private ================================ + + private XamlMember GetXamlAttributeProperty(XamlParserContext context, XamlPropertyName propName, + XamlType tagType, string tagNamespace, bool tagIsRoot) + { + XamlMember prop = null; + string ns = context.GetAttributeNamespace(propName, tagNamespace); + + // No Namespace, == Unknown Property + if (ns == null) + { + XamlMember unknownProperty; + if (propName.IsDotted) + { + XamlType attachedOwnerType = new XamlType(string.Empty, propName.OwnerName, null, context.SchemaContext); + unknownProperty = new XamlMember(propName.Name, attachedOwnerType, true /*isAttachable*/); + } + else + { + unknownProperty = new XamlMember(propName.Name, tagType, false); + } + return unknownProperty; + } + + // Get the property (attached, normal, or directive) + if (propName.IsDotted) + { + prop = context.GetDottedProperty(tagType, tagNamespace, propName, tagIsRoot); + } + else + { + prop = context.GetNoDotAttributeProperty(tagType, propName, tagNamespace, ns, tagIsRoot); + } + + return prop; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlName.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlName.cs new file mode 100644 index 00000000000..1c9fd269188 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlName.cs @@ -0,0 +1,100 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Globalization; +using System.Xaml.MS.Impl; +using System.Collections.Generic; + +namespace MS.Internal.Xaml.Parser +{ + internal abstract class XamlName + { + public const char PlusSign = '+'; + public const char UnderScore = '_'; + public const char Dot = '.'; + + public string Name { get; protected set; } + + protected XamlName() : this(string.Empty) { } + + public XamlName(string name) + { + Name = name; + } + + public XamlName(string prefix, string name) + { + Name = name; + _prefix = prefix ?? string.Empty; + } + + public abstract string ScopedName { get; } + + protected string _prefix; + protected string _namespace = null; + + public string Prefix { get { return _prefix; } } + public string Namespace { get { return _namespace; } } + + public static bool ContainsDot(string name) + { + return name.Contains("."); + } + + public static bool IsValidXamlName(string name) + { + if (name.Length == 0) + { + return false; + } + + if (!IsValidNameStartChar(name[0])) + { + return false; + } + + for (int i = 1; i < name.Length; i++) + { + if (!IsValidNameChar(name[i])) + { + return false; + } + } + + return true; + } + + public static bool IsValidNameStartChar(char ch) + { + return char.IsLetter(ch) || ch == UnderScore; + } + + public static bool IsValidNameChar(char ch) + { + if (IsValidNameStartChar(ch) || char.IsDigit(ch)) + { + return true; + } + + var unicodeCategory = char.GetUnicodeCategory(ch); + if (unicodeCategory == UnicodeCategory.NonSpacingMark || unicodeCategory == UnicodeCategory.SpacingCombiningMark) + { + return true; + } + return false; + } + + public static bool IsValidQualifiedNameChar(char ch) + { + return ch == Dot || IsValidNameChar(ch); + } + + public static bool IsValidQualifiedNameCharPlus(char ch) + { + return IsValidQualifiedNameChar(ch) || ch == PlusSign; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlPropertyName.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlPropertyName.cs new file mode 100644 index 00000000000..cd6978daa93 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlPropertyName.cs @@ -0,0 +1,103 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Xaml.MS.Impl; +using System.Collections.Generic; + +namespace MS.Internal.Xaml.Parser +{ + internal class XamlPropertyName : XamlName + { + private XamlPropertyName(XamlName owner, string prefix, string name) + : base(name) + { + if (owner != null) + { + this.Owner = owner; + this._prefix = owner.Prefix ?? String.Empty; + } + else + this._prefix = prefix ?? String.Empty; + } + + public readonly XamlName Owner; + + public static XamlPropertyName Parse(string longName) + { + if(String.IsNullOrEmpty(longName)) + { + return null; + } + + string prefix; + string dottedName; + + if (!XamlQualifiedName.Parse(longName, out prefix, out dottedName)) + { + return null; + } + + int start = 0; + string owner = String.Empty; + + int dotIdx = dottedName.IndexOf('.'); + if (dotIdx != -1) + { + owner = dottedName.Substring(start, dotIdx); + + if (String.IsNullOrEmpty(owner)) + { + return null; + } + + start = dotIdx + 1; + } + + string name = (start == 0) ? dottedName : dottedName.Substring(start); + + XamlQualifiedName ownerName = null; + if (!String.IsNullOrEmpty(owner)) + { + ownerName = new XamlQualifiedName(prefix, owner); + } + + XamlPropertyName propName = new XamlPropertyName(ownerName, prefix, name); + return propName; + } + + public static XamlPropertyName Parse(string longName, string namespaceURI) + { + XamlPropertyName propName = Parse(longName); + propName._namespace = namespaceURI; + return propName; + } + + public override string ScopedName + { + get + { + return IsDotted ? + Owner.ScopedName + "." + Name : + Name; + } + } + + public string OwnerName + { + get + { + return IsDotted ? + Owner.Name : + String.Empty; + } + } + + public bool IsDotted + { + get { return Owner != null; } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlPullParser.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlPullParser.cs new file mode 100644 index 00000000000..c48ea5b3f74 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlPullParser.cs @@ -0,0 +1,1199 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Xaml; +using System.Xml; +using System.Collections.Generic; +using System.Diagnostics; +using MS.Internal.Xaml.Context; +using System.Xaml.Schema; +using System.Xaml.MS.Impl; +using System.Collections; + +namespace MS.Internal.Xaml.Parser +{ + internal class XamlPullParser + { + XamlParserContext _context; + XamlScanner _xamlScanner; + XamlXmlReaderSettings _settings; + + public XamlPullParser(XamlParserContext context, XamlScanner scanner, XamlXmlReaderSettings settings) + { + _context = context; + _xamlScanner = scanner; + _settings = settings; + } + + // ===================================================== + + // Document ::= PREFIXDEFINITION* Element + // Element ::= EmptyElement | (StartElement ElementBody) + // EmptyElement ::= EMPTYELEMENT DIRECTIVE* ATTRIBUTE* + // StartElement ::= ELEMENT DIRECTIVE* + // ElementBody ::= ATTRIBUTE* ( PropertyElement | ElementContent+ )* ENDTAG + // PropertyElement ::= EmptyPropertyElement | NonemptyPropertyElement + // EmptyPropertyElement ::= EMPTYPROPERTYELEMENT + // NonemptyPropertyElement ::= PROPERTYELEMENT PropertyContent* ENDTAG + // ElementContent ::= ( PREFIXDEFINITION* Element ) | TEXT + // PropertyContent ::= ( PREFIXDEFINITION* Element ) | TEXT + // + // Attribute and Directive values can be markup extensions. + + + /////////////////////////// + // Document::= PREFIXDEFINITION* Element + // + public IEnumerable Parse() + { + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + + ScannerNodeType nodeType = _xamlScanner.NodeType; + while (nodeType == ScannerNodeType.PREFIXDEFINITION) + { + yield return Logic_PrefixDefinition(); + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + nodeType = _xamlScanner.NodeType; + } + + foreach (XamlNode node in P_Element()) + { + yield return node; + } + } + + // ===================================================== + + /////////////////////////// + // Element ::= EmptyElement | (StartElement ElementBody) + // + public IEnumerable P_Element() + { + ScannerNodeType nodeType = _xamlScanner.NodeType; + + switch (nodeType) + { + case ScannerNodeType.EMPTYELEMENT: + foreach (XamlNode node in P_EmptyElement()) + { + yield return node; + } + break; + + case ScannerNodeType.ELEMENT: + foreach (XamlNode node in P_StartElement()) + { + yield return node; + } + foreach (XamlNode node in P_ElementBody()) + { + yield return node; + } + break; + default: + throw new XamlUnexpectedParseException(_xamlScanner, nodeType, + SR.Get(SRID.ElementRuleException)); + } + } + + /////////////////////////// + // EmptyElement ::= EMPTYELEMENT DIRECTIVE* ATTRIBUTE* + // + public IEnumerable P_EmptyElement() + { + if (_xamlScanner.NodeType != ScannerNodeType.EMPTYELEMENT) + { + throw new XamlUnexpectedParseException(_xamlScanner, _xamlScanner.NodeType, + SR.Get(SRID.EmptyElementRuleException)); + } + yield return Logic_StartObject(_xamlScanner.Type, _xamlScanner.Namespace); + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + + while (_xamlScanner.NodeType == ScannerNodeType.DIRECTIVE) + { + // Directives are processed exactly like Attributes. + foreach (XamlNode node in LogicStream_Attribute()) + { + yield return node; + } + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + } + while (_xamlScanner.NodeType == ScannerNodeType.ATTRIBUTE) + { + foreach (XamlNode node in LogicStream_Attribute()) + { + yield return node; + } + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + } + + yield return Logic_EndOfAttributes(); + yield return Logic_EndObject(); + } + + /////////////////////////// + // StartElement ::= ELEMENT DIRECTIVE* + // + public IEnumerable P_StartElement() + { + if (_xamlScanner.NodeType != ScannerNodeType.ELEMENT) + { + throw new XamlUnexpectedParseException(_xamlScanner, _xamlScanner.NodeType, + SR.Get(SRID.StartElementRuleException)); + } + yield return Logic_StartObject(_xamlScanner.Type, _xamlScanner.Namespace); + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + + while (_xamlScanner.NodeType == ScannerNodeType.DIRECTIVE) + { + // Directives are processed exactly like Attributes. + foreach (XamlNode node in LogicStream_Attribute()) + { + yield return node; + } + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + } + } + + /////////////////////////// + // ElementBody ::= ATTRIBUTE* ( PropertyElement | ElementContent+ )* ENDTAG + // + public IEnumerable P_ElementBody() + { + while (_xamlScanner.NodeType == ScannerNodeType.ATTRIBUTE) + { + foreach (XamlNode node in LogicStream_Attribute()) + { + yield return node; + } + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + } + + yield return Logic_EndOfAttributes(); + + bool doneWithElementContent = false; + bool hasContent = false; + do + { + ScannerNodeType nodeType = _xamlScanner.NodeType; + switch (nodeType) + { + case ScannerNodeType.PROPERTYELEMENT: + case ScannerNodeType.EMPTYPROPERTYELEMENT: + hasContent = true; + foreach (XamlNode node in P_PropertyElement()) + { + yield return node; + } + break; + + case ScannerNodeType.PREFIXDEFINITION: + case ScannerNodeType.ELEMENT: + case ScannerNodeType.EMPTYELEMENT: + case ScannerNodeType.TEXT: + hasContent = true; + do + { + foreach (XamlNode node in P_ElementContent()) + { + yield return node; + } + nodeType = _xamlScanner.NodeType; + } while (nodeType == ScannerNodeType.PREFIXDEFINITION + || nodeType == ScannerNodeType.ELEMENT + || nodeType == ScannerNodeType.EMPTYELEMENT + || nodeType == ScannerNodeType.TEXT); + + // If the above started a container directive or an unknown content property, then end the collection. + if (_context.CurrentInItemsProperty || _context.CurrentInInitProperty || _context.CurrentInUnknownContent) + { + yield return Logic_EndMember(); // Container or unknown content property. + + if (_context.CurrentInCollectionFromMember) + { + yield return Logic_EndObject(); // Getter pseudo Object + yield return Logic_EndMember(); // Content Property + _context.CurrentInCollectionFromMember = false; + if (_context.CurrentInImplicitArray) + { + _context.CurrentInImplicitArray = false; + yield return Logic_EndObject(); + yield return Logic_EndMember(); + } + } + } + break; + case ScannerNodeType.ENDTAG: + // if foo has no default constructor we need to output SM _Initialization V "" EM + XamlType currentType = _context.CurrentType; + bool hasTypeConverter = currentType.TypeConverter != null; + bool isConstructable = currentType.IsConstructible && !currentType.ConstructionRequiresArguments; + if (!hasContent && hasTypeConverter && !isConstructable) + { + yield return Logic_StartInitProperty(currentType); + yield return new XamlNode(XamlNodeType.Value, string.Empty); + yield return Logic_EndMember(); + } + doneWithElementContent = true; + break; + default: + doneWithElementContent = true; + break; + } + } while (!doneWithElementContent); + + if (_xamlScanner.NodeType != ScannerNodeType.ENDTAG) + { + throw new XamlUnexpectedParseException(_xamlScanner, _xamlScanner.NodeType, + SR.Get(SRID.ElementBodyRuleException)); + } + yield return Logic_EndObject(); + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + } + + /////////////////////////// + // PropertyElement ::= EmptyPropertyElement | NonemptyPropertyElement + // + public IEnumerable P_PropertyElement() + { + ScannerNodeType nodeType = _xamlScanner.NodeType; + + switch (nodeType) + { + case ScannerNodeType.EMPTYPROPERTYELEMENT: + foreach (XamlNode node in P_EmptyPropertyElement()) + { + yield return node; + } + break; + case ScannerNodeType.PROPERTYELEMENT: + foreach (XamlNode node in P_NonemptyPropertyElement()) + { + yield return node; + } + break; + default: + throw new XamlUnexpectedParseException(_xamlScanner, nodeType, + SR.Get(SRID.PropertyElementRuleException)); + } + } + + /////////////////////////// + // EmptyPropertyElement ::= EMPTYPROPERTYELEMENT + // + public IEnumerable P_EmptyPropertyElement() + { + if (_xamlScanner.NodeType != ScannerNodeType.EMPTYPROPERTYELEMENT) + { + throw new XamlUnexpectedParseException(_xamlScanner, _xamlScanner.NodeType, + SR.Get(SRID.EmptyPropertyElementRuleException)); + } + yield return Logic_StartMember(_xamlScanner.PropertyElement); + yield return Logic_EndMember(); + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + } + + /////////////////////////// + // NonemptyPropertyElement ::= PROPERTYELEMENT PropertyContent* ENDTAG + // + public IEnumerable P_NonemptyPropertyElement() + { + if (_xamlScanner.NodeType != ScannerNodeType.PROPERTYELEMENT) + { + throw new XamlUnexpectedParseException(_xamlScanner, _xamlScanner.NodeType, + SR.Get(SRID.NonemptyPropertyElementRuleException)); + } + yield return Logic_StartMember(_xamlScanner.PropertyElement); + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + + bool doingPropertyContent = true; + do + { + ScannerNodeType nodeType = _xamlScanner.NodeType; + switch (nodeType) + { + case ScannerNodeType.PREFIXDEFINITION: + case ScannerNodeType.ELEMENT: + case ScannerNodeType.EMPTYELEMENT: + case ScannerNodeType.TEXT: + do + { + foreach (XamlNode node in P_PropertyContent()) + { + yield return node; + } + nodeType = _xamlScanner.NodeType; + } while (nodeType == ScannerNodeType.PREFIXDEFINITION + || nodeType == ScannerNodeType.ELEMENT + || nodeType == ScannerNodeType.EMPTYELEMENT + || nodeType == ScannerNodeType.TEXT); + // If the above started a container directive, end the collection. + if (_context.CurrentInItemsProperty || _context.CurrentInInitProperty) + { + yield return Logic_EndMember(); // Pseudo container property. + + if (_context.CurrentInCollectionFromMember) + { + yield return Logic_EndObject(); // Getter pseudo Object + _context.CurrentInCollectionFromMember = false; + if (_context.CurrentInImplicitArray) + { + _context.CurrentInImplicitArray = false; + yield return Logic_EndMember(); + yield return Logic_EndObject(); + } + } + } + break; + default: + doingPropertyContent = false; + break; + } + } while (doingPropertyContent); + + + if (_xamlScanner.NodeType != ScannerNodeType.ENDTAG) + { + throw new XamlUnexpectedParseException(_xamlScanner, _xamlScanner.NodeType, + SR.Get(SRID.NonemptyPropertyElementRuleException)); + } + yield return Logic_EndMember(); + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + } + + /////////////////////////// + // ElementContent ::= ( PREFIXDEFINITION* Element ) | TEXT + // + public IEnumerable P_ElementContent() + { + XamlType currentType = _context.CurrentType; + + List savedPrefixDefinitions = null; + ScannerNodeType nodeType = _xamlScanner.NodeType; + switch (nodeType) + { + case ScannerNodeType.PREFIXDEFINITION: + case ScannerNodeType.ELEMENT: + case ScannerNodeType.EMPTYELEMENT: + case ScannerNodeType.TEXT: + if (nodeType == ScannerNodeType.TEXT) + { + XamlText text = _xamlScanner.TextContent; + + if (Logic_IsDiscardableWhitespace(text)) + { + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + break; + } + } + + // Don't immediatly emit the prefix Definitions. + // buffer them for moment because if this is the first object + // in a collection, we may need to jam an implicit _Items property + // on Content Property in before the PrefixDef's and then the ObjectType. + while (nodeType == ScannerNodeType.PREFIXDEFINITION) + { + if (savedPrefixDefinitions == null) + { + savedPrefixDefinitions = new List(); + } + if (ProvideLineInfo) + { + savedPrefixDefinitions.Add(Logic_LineInfo()); + } + savedPrefixDefinitions.Add(Logic_PrefixDefinition()); + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + nodeType = _xamlScanner.NodeType; + } + + // Check for any preambles we need to emit before the + // emitting the actual element or Text. + bool isTextInitialization = false; + if (!_context.CurrentInItemsProperty && !_context.CurrentInUnknownContent) + { + bool isContentProperty = false; + // In case of text, we look first for a string or object content property, + // then a TypeConverter + if (nodeType == ScannerNodeType.TEXT) + { + if (currentType.ContentProperty != null && CanAcceptString(currentType.ContentProperty)) + { + isContentProperty = true; + } + // If there have been "real" properties then we are forced to use the + // Consturctor. Otherwise we can consider a TypeConverter on the TEXT. + else if (!_context.CurrentForcedToUseConstructor + && !_xamlScanner.TextContent.IsEmpty + && currentType.TypeConverter != null) + { + isTextInitialization = true; + } + } + // Otherwise, we look first for a collection, and then fall back to content property + if (!isTextInitialization && !isContentProperty) + { + // If we are first in a collection + if (currentType.IsCollection || currentType.IsDictionary) + { + yield return Logic_StartItemsProperty(currentType); + } + else // Back to ContentProperty (either element or unknown content) + { + isContentProperty = true; + } + } + // Don't yield more than one unknown content property for multiple, + // contiguous content objects and values. + if (isContentProperty && !_context.CurrentInUnknownContent) + { + XamlMember contentProperty = currentType.ContentProperty; + if (contentProperty != null) + { + bool isVisible = _context.IsVisible( + contentProperty, _context.CurrentTypeIsRoot ? _context.CurrentType : null); + // Visible content properties produce known members. + // Invisible content properties produce unknown members. + // Protected content properties of root instances and internal + // content properties can be visible, depending on the reader settings. + if (!isVisible) + { + // We use the current type, not the actual declaring type of the non-visible property, + // for consistency with how non-visible PEs and Attribute Properties are handled. + contentProperty = new XamlMember(contentProperty.Name, currentType, false); + } + } + // A null argument produces an unknown content member. + yield return Logic_StartContentProperty(contentProperty); + + // Check for and emit the get collection from member. + foreach (XamlNode node in LogicStream_CheckForStartGetCollectionFromMember()) + { + yield return node; + } + } + } + + // Now we are ready for the given element. + // so now emit the saved prefix definitions. + if (savedPrefixDefinitions != null) + { + for (int i = 0; i < savedPrefixDefinitions.Count; i++) + { + yield return savedPrefixDefinitions[i]; + } + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + } + + if (nodeType == ScannerNodeType.TEXT) + { + XamlText text = _xamlScanner.TextContent; + string trimmed = Logic_ApplyFinalTextTrimming(text); + bool isXDataText = _xamlScanner.IsXDataText; + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + + if (trimmed == String.Empty) + { + break; + } + + if (isTextInitialization) + { + yield return Logic_StartInitProperty(currentType); + } + + if (isXDataText) + { + yield return Logic_StartObject(XamlLanguage.XData, null); + XamlMember xDataTextProperty = XamlLanguage.XData.GetMember("Text"); + yield return Logic_EndOfAttributes(); + yield return Logic_StartMember(xDataTextProperty); + } + + yield return new XamlNode(XamlNodeType.Value, trimmed); + + if (isXDataText) + { + yield return Logic_EndMember(); + yield return Logic_EndObject(); ; + } + } + else + { + foreach (XamlNode node in P_Element()) + { + yield return node; + } + } + + // If we are not in an items or unknown content property, then + // there cannot be more objects or values that follow this content + // (a singular property), and thus we can end this property now. + if (!_context.CurrentInItemsProperty && !_context.CurrentInUnknownContent) + { + yield return Logic_EndMember(); + } + break; + } // end switch + } + + /////////////////////////// + // PropertyContent ::= ( PREFIXDEFINITION* Element ) | TEXT + // + public IEnumerable P_PropertyContent() + { + ScannerNodeType nodeType = _xamlScanner.NodeType; + List _savedPrefixDefinitions = null; + string trimmed = String.Empty; + bool isTextXML = false; + + switch (nodeType) + { + case ScannerNodeType.PREFIXDEFINITION: + case ScannerNodeType.ELEMENT: + case ScannerNodeType.EMPTYELEMENT: + case ScannerNodeType.TEXT: + if (nodeType == ScannerNodeType.TEXT) + { + XamlText text = _xamlScanner.TextContent; + + if (Logic_IsDiscardableWhitespace(text)) + { + trimmed = String.Empty; + } + else + { + trimmed = Logic_ApplyFinalTextTrimming(text); + } + + isTextXML = _xamlScanner.IsXDataText; + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + if (trimmed == String.Empty) + { + break; + } + } + + // Don't immediatly emit the prefix Definitions. + // buffer them for moment because if this is the first object + // in a collection, we may need to jam an implicit _Items property + // in before the PrefixDef's and then the ObjectType. + while (nodeType == ScannerNodeType.PREFIXDEFINITION) + { + if (_savedPrefixDefinitions == null) + { + _savedPrefixDefinitions = new List(); + } + _savedPrefixDefinitions.Add(Logic_PrefixDefinition()); + if (ProvideLineInfo) + { + _savedPrefixDefinitions.Add(Logic_LineInfo()); + } + _xamlScanner.Read(); + if (ProvideLineInfo) + { + yield return Logic_LineInfo(); + } + nodeType = _xamlScanner.NodeType; + } + + // If this is TEXT and the current Property has a TypeConverter + // Then emit the TEXT now. + if (nodeType == ScannerNodeType.TEXT + && _context.CurrentMember.TypeConverter != null) + { + yield return new XamlNode(XamlNodeType.Value, trimmed); + } + else + { + // Check for any preambles we need to emit before the + // emitting the actual element or Text. + if (!_context.CurrentInCollectionFromMember) + { + // Check for and emit the get collection from member. + foreach (XamlNode node in LogicStream_CheckForStartGetCollectionFromMember()) + { + yield return node; + } + } + + // We couldn't emit text in the code above (directly under the property). + // We have now (possibly) started a get collection from member. This TEXT might go + // under the _items. + // This might be . + // It might still be an error, ie. Unknown Content. + // This is the last chance to emit the TEXT. + if (nodeType == ScannerNodeType.TEXT) + { + if (isTextXML) + { + yield return Logic_StartObject(XamlLanguage.XData, null); + XamlMember xDataTextProperty = XamlLanguage.XData.GetMember("Text"); + yield return Logic_EndOfAttributes(); + yield return Logic_StartMember(xDataTextProperty); + } + + yield return new XamlNode(XamlNodeType.Value, trimmed); + + if (isTextXML) + { + yield return Logic_EndMember(); + yield return Logic_EndObject(); ; + } + } + else + { + // Now we are ready for the given element. + // now emit the saved prefix definitions. + if (_savedPrefixDefinitions != null) + { + for (int i = 0; i < _savedPrefixDefinitions.Count; i++) + { + yield return _savedPrefixDefinitions[i]; + } + } + + foreach (XamlNode node in P_Element()) + { + yield return node; + } + } + } + break; + } + } + + // ---------- Private properties --------------- + + private int LineNumber + { + get { return _xamlScanner.LineNumber; } + } + + private int LinePosition + { + get { return _xamlScanner.LinePosition; } + } + + private bool ProvideLineInfo + { + get { return _settings.ProvideLineInfo; } + } + + // =================== Logic Functions ======================== + + private XamlNode Logic_LineInfo() + { + LineInfo lineInfo = new LineInfo(LineNumber, LinePosition); + XamlNode lineInfoNode = new XamlNode(lineInfo); + return lineInfoNode; + } + + private XamlNode Logic_PrefixDefinition() + { + string prefix = _xamlScanner.Prefix; + string xamlNs = _xamlScanner.Namespace; + XamlNode addNs = new XamlNode(XamlNodeType.NamespaceDeclaration, new NamespaceDeclaration(xamlNs, prefix)); + return addNs; + } + + private XamlNode Logic_StartObject(XamlType xamlType, string xamlNamespace) + { + _context.PushScope(); + _context.CurrentType = xamlType; + _context.CurrentTypeNamespace = xamlNamespace; + + XamlNode startObj = new XamlNode(XamlNodeType.StartObject, xamlType); + return startObj; + } + + private XamlNode Logic_EndObject() + { + XamlType xamlType = _context.CurrentType; + + _context.PopScope(); + _context.CurrentPreviousChildType = xamlType; + + XamlNode endObj = new XamlNode(XamlNodeType.EndObject); + return endObj; + } + + private IEnumerable LogicStream_Attribute() + { + XamlMember property = _xamlScanner.PropertyAttribute; + XamlText text = _xamlScanner.PropertyAttributeText; + + if (_xamlScanner.IsCtorForcingMember) + { + _context.CurrentForcedToUseConstructor = true; + } + + XamlNode startProperty = new XamlNode(XamlNodeType.StartMember, property); + yield return startProperty; + + if (text.LooksLikeAMarkupExtension) + { + MePullParser me = new MePullParser(_context); + foreach (XamlNode node in me.Parse(text.Text, LineNumber, LinePosition)) + { + yield return node; + } + } + else + { + XamlNode textNode = new XamlNode(XamlNodeType.Value, text.AttributeText); + yield return textNode; + } + yield return new XamlNode(XamlNodeType.EndMember); + } + + private XamlNode Logic_EndOfAttributes() + { + var endOfAttributes = new XamlNode(XamlNode.InternalNodeType.EndOfAttributes); + return endOfAttributes; + } + + private XamlNode Logic_StartMember(XamlMember member) + { + _context.CurrentMember = member; + if (_xamlScanner.IsCtorForcingMember) + { + _context.CurrentForcedToUseConstructor = true; + } + XamlType memberXamlType = member.Type; + _context.CurrentInContainerDirective = member.IsDirective && (memberXamlType != null && (memberXamlType.IsCollection || memberXamlType.IsDictionary)); + + var startMember = new XamlNode(XamlNodeType.StartMember, member); + return startMember; + } + + private XamlNode Logic_EndMember() + { + _context.CurrentMember = null; + _context.CurrentPreviousChildType = null; + _context.CurrentInContainerDirective = false; + return new XamlNode(XamlNodeType.EndMember); + } + + private XamlNode Logic_StartContentProperty(XamlMember property) + { + if (property == null) + { + property = XamlLanguage.UnknownContent; + } + _context.CurrentMember = property; + var startProperty = new XamlNode(XamlNodeType.StartMember, property); + // SetLineInfo(startProperty); // No line number info for objects from members. + return startProperty; + } + + private XamlNode Logic_StartInitProperty(XamlType ownerType) + { + var initProperty = XamlLanguage.Initialization; + + _context.CurrentMember = initProperty; + + var startProperty = new XamlNode(XamlNodeType.StartMember, initProperty); + // SetLineInfo(startProperty); // No line number info for implicit properties. + return startProperty; + } + + private string Logic_ApplyFinalTextTrimming(XamlText text) + { + ScannerNodeType nextNodeType = _xamlScanner.PeekNodeType; + string trimmed = text.Text; + + if (!text.IsSpacePreserved) + { + // Trim trailing space from text if it is the last bit of content. + // End Element and End Property Element and Start of PE all end "content" + if (nextNodeType == ScannerNodeType.ENDTAG || nextNodeType == ScannerNodeType.PROPERTYELEMENT || nextNodeType == ScannerNodeType.EMPTYPROPERTYELEMENT) + { + trimmed = XamlText.TrimTrailingWhitespace(trimmed); + } + + // If the text is the first thing, ie. before any element + // OR the previous element was "TrimSurroundingWhitespace" + // then trim leading Whitespace. + XamlType previousObject = _context.CurrentPreviousChildType; + if (previousObject == null || previousObject.TrimSurroundingWhitespace) + { + trimmed = XamlText.TrimLeadingWhitespace(trimmed); + } + + // If next element is "TrimSurroundingWhitespace", trim trailing WS. + if (nextNodeType == ScannerNodeType.ELEMENT + || nextNodeType == ScannerNodeType.EMPTYELEMENT) + { + XamlType nextXamlType = _xamlScanner.PeekType; + if (nextXamlType.TrimSurroundingWhitespace) + { + trimmed = XamlText.TrimTrailingWhitespace(trimmed); + } + } + } + return trimmed; + } + + private XamlNode Logic_StartGetObjectFromMember(XamlType realType) + { + _context.PushScope(); + _context.CurrentType = realType; + _context.CurrentInCollectionFromMember = true; + + var startObj = new XamlNode(XamlNodeType.GetObject); + return startObj; + } + + private XamlNode Logic_StartItemsProperty(XamlType collectionType) + { + _context.CurrentMember = XamlLanguage.Items; + _context.CurrentInContainerDirective = true; + + var startProperty = new XamlNode(XamlNodeType.StartMember, XamlLanguage.Items); + //SetLineInfo(startProperty); // No line number info for implicit properties. + return startProperty; + } + + #region Optimizations + private readonly XamlTypeName arrayType = new XamlTypeName(@"http://schemas.microsoft.com/winfx/2006/xaml", "Array"); + private XamlType _arrayExtensionType = null; + private XamlType ArrayExtensionType + { + get + { + if (_arrayExtensionType == null) + { + _arrayExtensionType = _context.GetXamlType(arrayType); + } + return _arrayExtensionType; + } + } + + private XamlMember _arrayTypeMember = null; + private XamlMember ArrayTypeMember + { + get + { + if (_arrayTypeMember == null) + { + _arrayTypeMember = _context.GetXamlProperty(ArrayExtensionType, @"Type", null); + } + return _arrayTypeMember; + } + } + + private XamlMember _itemsTypeMember = null; + private XamlMember ItemsTypeMember + { + get + { + if (_itemsTypeMember == null) + { + _itemsTypeMember = _context.GetXamlProperty(ArrayExtensionType, @"Items", null); + } + return _itemsTypeMember; + } + } + #endregion + + private IEnumerable LogicStream_CheckForStartGetCollectionFromMember() + { + XamlType currentType = _context.CurrentType; + XamlMember currentProperty = _context.CurrentMember; + + XamlType propertyType = currentProperty.Type; + + XamlType valueElementType = (_xamlScanner.NodeType == ScannerNodeType.TEXT) + ? XamlLanguage.String + : _xamlScanner.Type; + + if (propertyType.IsArray && _xamlScanner.Type != ArrayExtensionType) + { + IEnumerable newNamespaces = null; + XamlTypeName typeName = new XamlTypeName(propertyType.ItemType); + INamespacePrefixLookup prefixResolver = new NamespacePrefixLookup(out newNamespaces, _context.FindNamespaceByPrefix); + string typeNameString = typeName.ToString(prefixResolver); // SideEffects!!! prefixResolver will populate newNamespaces + + foreach (NamespaceDeclaration nsDecl in newNamespaces) + { + yield return new XamlNode(XamlNodeType.NamespaceDeclaration, nsDecl); + } + yield return Logic_StartObject(ArrayExtensionType, null); + _context.CurrentInImplicitArray = true; + yield return Logic_StartMember(ArrayTypeMember); + + yield return new XamlNode(XamlNodeType.Value, typeNameString); + yield return Logic_EndMember(); + yield return Logic_EndOfAttributes(); + yield return Logic_StartMember(ItemsTypeMember); + + currentType = _context.CurrentType; + currentProperty = _context.CurrentMember; + propertyType = currentProperty.Type; + } + + // Now Consider inserting special preamble to "Get" the collection: + // . GO + // . . SM _items + if (!currentProperty.IsDirective && (propertyType.IsCollection || propertyType.IsDictionary)) + { + bool emitPreamble = false; + + // If the collection property is Readonly then "Get" the collection. + if (currentProperty.IsReadOnly || !_context.CurrentMemberIsWriteVisible()) + { + emitPreamble = true; + } + // If the collection is R/W and there is a type converter and we have Text + // use the type converter rather than the GO; SM _items; + else if (propertyType.TypeConverter != null && !currentProperty.IsReadOnly + && _xamlScanner.NodeType == ScannerNodeType.TEXT) + { + emitPreamble = false; + } + // Or if the Value (this is the first value in the collection) + // isn't assignable to the Collection then "Get" the collection. + else if (valueElementType == null || !valueElementType.CanAssignTo(propertyType)) + { + if (valueElementType != null) + { + // Unless: the Value is a Markup extension, in which case it is + // assumed that the ProvideValue() type will be AssignableFrom + // or If the next object has an x:Key in which case it must be + // a dictionary entry. + // so Don't "Get" the collection. + if (!valueElementType.IsMarkupExtension || _xamlScanner.HasKeyAttribute) + { + emitPreamble = true; + } + // Except: the Array Extension can never return a dictionary + // so for Array Extension do "Get" the collection. + // Note Array Extension would be suitable for List Collections + // Note: a fully validating parser should look at MarkupExtensionReturnType + // for this choice, there might be other MarkupExtensions that fit this. + else if (valueElementType == XamlLanguage.Array) + { + emitPreamble = true; + } + } + } + if (emitPreamble) + { + yield return Logic_StartGetObjectFromMember(propertyType); + yield return Logic_StartItemsProperty(propertyType); + } + } + } + + /// + /// Returns true if whitespace is discardable at this phase in + /// the parsing. Here we discard whitespace between property elements + /// but keep it between object elements for collections that accept it. + /// Discarding trailing whitespace in collections cannot be decided here. + /// [see: Logic_ReadAhead_ApplyFinalTextTrimming + /// + /// + /// + private bool Logic_IsDiscardableWhitespace(XamlText text) + { + if (!text.IsWhiteSpaceOnly) + { + return false; + } + else + { + // Force unknown members to behave as whitespace significant collections in order to preserve as much information as possible. + if (_context.CurrentMember != null && _context.CurrentMember.IsUnknown) + { + return false; + } + else if (_context.CurrentInContainerDirective) + { + XamlType collectionType = _context.CurrentMember == XamlLanguage.Items ? _context.CurrentType : _context.CurrentMember.Type; + if (collectionType.IsWhitespaceSignificantCollection) + { + return false; + } + } + else + { + // Whitespace, by itself does not start content. Eg. The WS between + // the Start Element and the first Property Element is not content, but + // the WS between the Start Element and the first child Element (ie. other content) + // is content. + XamlMember prop = _context.CurrentMember; + if (_xamlScanner.PeekNodeType == ScannerNodeType.ELEMENT) + { + if (prop == null) + { + prop = _context.CurrentType.ContentProperty; + } + if (prop != null && prop.Type != null && prop.Type.IsWhitespaceSignificantCollection) + { + return false; + } + if (prop == null && _context.CurrentType.IsWhitespaceSignificantCollection) + { + return false; + } + } + // Whitespace can also start content if space is preserved and it's at the end of an element and... + else if (text.IsSpacePreserved && _xamlScanner.PeekNodeType == ScannerNodeType.ENDTAG) + { + // ...it's by itself in a PE with no other children + if (prop != null) + { + if (_context.CurrentPreviousChildType == null) + { + return false; + } + } + // ...it's in an element with a string content property + else if (_context.CurrentType.ContentProperty != null) + { + prop = _context.CurrentType.ContentProperty; + // For backcompat we need to suppport CPs of type object here. + // Theoretically we'd also like to support all type-convertible CPs. + // However, for non-string CPs, 3.0 only surfaced whitespace as text if + // the CP hadn't already been set. For string, it surfaced it in all cases. + // So to avoid a breaking change, we only surface string right now. + if (prop.Type == XamlLanguage.String) + { + return false; + } + if (prop.Type.IsWhitespaceSignificantCollection) + { + return false; + } + } + // ...it's in a type-convertible element + else if (_context.CurrentType.TypeConverter != null && !_context.CurrentForcedToUseConstructor) + { + return false; + } + } + } + } + return true; + } + + private static bool CanAcceptString(XamlMember property) + { + if (property == null) + { + return false; + } + if (property.TypeConverter == BuiltInValueConverter.String) + { + return true; + } + if (property.TypeConverter == BuiltInValueConverter.Object) + { + return true; + } + XamlType propertyType = property.Type; + if (propertyType.IsCollection) + { + foreach (XamlType allowedType in propertyType.AllowedContentTypes) + { + if (allowedType == XamlLanguage.String || allowedType == XamlLanguage.Object) + { + return true; + } + } + } + return false; + } + } + + [Serializable] // FxCop advised this be Serializable. + class XamlUnexpectedParseException : XamlParseException + { + public XamlUnexpectedParseException() { } + + // FxCop says this is never called + //public XamlUnexpectedParseException(string message) + // : base(message) { } + + // FxCop says this is never called + //public XamlUnexpectedParseException(string message, Exception innerException) + // : base(message, innerException) { } + + public XamlUnexpectedParseException(XamlScanner xamlScanner, ScannerNodeType nodetype, string parseRule) + : base(xamlScanner, SR.Get(SRID.UnexpectedNodeType, nodetype.ToString(), parseRule)) { } + + protected XamlUnexpectedParseException(System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) + : base(info, context) { } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlQualifiedName.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlQualifiedName.cs new file mode 100644 index 00000000000..84501868433 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlQualifiedName.cs @@ -0,0 +1,102 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Xaml.MS.Impl; +using System.Collections.Generic; + +namespace MS.Internal.Xaml.Parser +{ + internal class XamlQualifiedName : XamlName + { + public XamlQualifiedName(string prefix, string name) + : base(prefix, name) + { + } + + public override string ScopedName + { + get + { + return string.IsNullOrEmpty(Prefix) ? + Name : + Prefix + ":" + Name; + } + } + + internal static bool IsNameValid(string name) + { + if (name.Length == 0) + { + return false; + } + if (!XamlName.IsValidNameStartChar(name[0])) + { + return false; + } + for (int i = 1; i < name.Length; i++) + { + if (!XamlName.IsValidQualifiedNameChar(name[i])) + { + return false; + } + } + return true; + } + + internal static bool IsNameValid_WithPlus(string name) + { + if (name.Length == 0) + { + return false; + } + if (!XamlName.IsValidNameStartChar(name[0])) + { + return false; + } + for (int i = 1; i < name.Length; i++) + { + if (!XamlName.IsValidQualifiedNameCharPlus(name[i])) + { + return false; + } + } + return true; + } + + public static bool Parse(string longName, out string prefix, out string name) + { + int start = 0; + int colonIdx = longName.IndexOf(':'); + + prefix = String.Empty; + name = String.Empty; + + if (colonIdx != -1) + { + prefix = longName.Substring(start, colonIdx); + + if (String.IsNullOrEmpty(prefix) || !IsNameValid(prefix)) + { + return false; + } + + start = colonIdx + 1; + } + + name = (start==0) ? longName : longName.Substring(start); + + // we allow Internal type name (ie. Foo+Bar) on "trival" ie. "non-generic" type names. + // This is back compat with 3.0. + // Don't want to allow it in any of the new type name syntax. (including trival typeArgs) + if (String.IsNullOrEmpty(name) || !IsNameValid_WithPlus(name)) + { + return false; + } + + return true; + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlScanner.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlScanner.cs new file mode 100644 index 00000000000..23af41f07f7 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlScanner.cs @@ -0,0 +1,866 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Xml; +using System.Xaml; +using MS.Internal.Xaml.Context; +using System.Xaml.Schema; +using System.Xaml.MS.Impl; + +namespace MS.Internal.Xaml.Parser +{ + class XamlScanner + { + XmlReader _xmlReader; + IXmlLineInfo _xmlLineInfo; + + // XamlParserContext vs. XamlScannerStack + // The XamlScannerStack belongs to the Scanner (aka XamlScanner) exclusively. + // It has its own stack because it necessarily will read ahead sometimes. + // + // The XamlParserContext belongs to the Parser (aka XamlParser). + // Except the scanner loads namespaces into the Parser's XamlParserContext, + // and reads from it to resolve type names and namespace prefixes. + // + XamlScannerStack _scannerStack; + XamlParserContext _parserContext; + + XamlText _accumulatedText = null; + List _attributes; + int _nextAttribute; + XamlScannerNode _currentNode; + Queue _readNodesQueue; + XamlXmlReaderSettings _settings; + XamlAttribute _typeArgumentAttribute; + bool _hasKeyAttribute = false; + + internal XamlScanner(XamlParserContext context, XmlReader xmlReader, XamlXmlReaderSettings settings) + { + _xmlReader = xmlReader; + _xmlLineInfo = settings.ProvideLineInfo ? (xmlReader as IXmlLineInfo) : null; //consider removing the "settings" check + + _parserContext = context; + + _scannerStack = new XamlScannerStack(); + _readNodesQueue = new Queue(); + + _settings = settings; + if (settings.XmlSpacePreserve) + { + _scannerStack.CurrentXmlSpacePreserve = true; + } + } + + public void Read() + { + LoadQueue(); + _currentNode = _readNodesQueue.Dequeue(); + } + + public ScannerNodeType PeekNodeType + { + get + { + LoadQueue(); + return _readNodesQueue.Peek().NodeType; + } + } + + public XamlType PeekType + { + get + { + LoadQueue(); + return _readNodesQueue.Peek().Type; + } + } + + public ScannerNodeType NodeType + { + get { return _currentNode.NodeType; } + } + + public XamlType Type + { + get { return _currentNode.Type; } + } + + public XamlMember PropertyAttribute + { + get { return _currentNode.PropertyAttribute; } + } + + public XamlText PropertyAttributeText + { + get { return _currentNode.PropertyAttributeText; } + } + + public bool IsCtorForcingMember + { + get { return _currentNode.IsCtorForcingMember; } + } + + public XamlMember PropertyElement + { + get { return _currentNode.PropertyElement; } + } + + public XamlText TextContent + { + get { return _currentNode.TextContent; } + } + + public bool IsXDataText + { + get { return _currentNode.IsXDataText; } + } + + public bool HasKeyAttribute + { + get + { + return _hasKeyAttribute; + } + } + + public string Prefix + { + get { return _currentNode.Prefix; } + } + + public string Namespace + { + get { return _currentNode.TypeNamespace; } + } + + public int LineNumber + { + get { return _currentNode.LineNumber; } + } + + public int LinePosition + { + get { return _currentNode.LinePosition; } + } + + // =================================================================== + + private void LoadQueue() + { + if (_readNodesQueue.Count == 0) + { + DoXmlRead(); + } + } + + private void DoXmlRead() + { + while (_readNodesQueue.Count == 0) + { + if (_xmlReader.Read()) + { + ProcessCurrentXmlNode(); + } + else + { + // false from XML Read() is the same as reading .None. + ReadNone(); + } + } + } + + private void ProcessCurrentXmlNode() + { + XmlNodeType xmlNodeType = _xmlReader.NodeType; + switch (xmlNodeType) + { + case XmlNodeType.Element: + ReadElement(); + break; + + case XmlNodeType.EndElement: + ReadEndElement(); + break; + + case XmlNodeType.Text: + case XmlNodeType.CDATA: + ReadText(); + break; + + case XmlNodeType.SignificantWhitespace: + case XmlNodeType.Whitespace: + ReadWhitespace(); + break; + + case XmlNodeType.None: + ReadNone(); + break; + + default: + break; + } + } + // ============= Private ================================== + + private XamlText AccumulatedText + { + get + { + if (_accumulatedText == null) + { + _accumulatedText = new XamlText(_scannerStack.CurrentXmlSpacePreserve); + } + return _accumulatedText; + } + } + + private void ClearAccumulatedText() + { + _accumulatedText = null; + } + + private bool HaveAccumulatedText + { + get { return _accumulatedText != null && !_accumulatedText.IsEmpty; } + } + + // ============= Element Processing ================================== + + private void ReadElement() + { + // Accumulated text is enqueued a piece of content before this element + EnqueueAnyText(); + _hasKeyAttribute = false; + // Empty Elements are by definition leaf elements and they + // don't nest. So we don't need to stack this state. + bool isEmptyTag = _xmlReader.IsEmptyElement; + + string prefix = _xmlReader.Prefix; + string strippedName = _xmlReader.LocalName; + if (XamlName.ContainsDot(strippedName)) + { + Debug.Assert(_xmlReader.NodeType == XmlNodeType.Element); + XamlPropertyName name = XamlPropertyName.Parse(_xmlReader.Name, _xmlReader.NamespaceURI); + if (_scannerStack.CurrentType == null) + { + throw LineInfo(new XamlParseException(SR.Get(SRID.ParentlessPropertyElement, _xmlReader.Name))); + } + ReadPropertyElement(name, _scannerStack.CurrentType, _scannerStack.CurrentTypeNamespace, isEmptyTag); + } + else + { + XamlName name = new XamlQualifiedName(prefix, strippedName); + ReadObjectElement(name, isEmptyTag); + } + } + + // ReadObjectElement: reads the entire start tag. This may result in + // more than one Scanner Nodes. The results are enqueued onto a list + // rather than returned directly, then the caller can de-queue the nodes + // one at a time. + private void ReadObjectElement(XamlName name, bool isEmptyTag) + { + _typeArgumentAttribute = null; + XamlScannerNode node = new XamlScannerNode(_xmlLineInfo); + + // Scan for xmlns(s) before attempting to resolve the type. + // So while we are there, collect up all the attributes. + // Enqueue the xmlns attributes first. + // PostProcess and Enqueue the other attributes after. + PreprocessAttributes(); + + node.Prefix = name.Prefix; + node.IsEmptyTag = isEmptyTag; + + // It is possible for an application to provide XML nodes via XmlNodeReader + // where the URI is defined but there was no xmlns attribute for use to resolve against. + // See app Paperboy + Debug.Assert(_xmlReader.NodeType == XmlNodeType.Element); + string xamlNs = _xmlReader.NamespaceURI; + if (xamlNs == null) + { + ReadObjectElement_NoNamespace(name, node); + } + else // if (xamlNs != null) + { + node.TypeNamespace = xamlNs; + + // First check if the XML element is a + // Directive Property + // + XamlSchemaContext schemaContext = _parserContext.SchemaContext; + XamlMember dirProperty = schemaContext.GetXamlDirective(xamlNs, name.Name); + if (dirProperty != null) + { + ReadObjectElement_DirectiveProperty(dirProperty, node); + } + else // normal Element Case. + { + bool sawXData = ReadObjectElement_Object(xamlNs, name.Name, node); + if (sawXData) + { + return; + } + } + } + + _readNodesQueue.Enqueue(node); + + // Now add the processed attributes from the rest of the start tag. + while (HaveUnprocessedAttributes) + { + EnqueueAnotherAttribute(isEmptyTag); + } + } + + private void ReadObjectElement_NoNamespace(XamlName name, XamlScannerNode node) + { + XamlType errType = CreateErrorXamlType(name, string.Empty); + node.Type = errType; + + PostprocessAttributes(node); + + if (!node.IsEmptyTag) + { + node.NodeType = ScannerNodeType.ELEMENT; + _scannerStack.Push(node.Type, node.TypeNamespace); + } + else + { + node.NodeType = ScannerNodeType.EMPTYELEMENT; + } + } + + private void ReadObjectElement_DirectiveProperty(XamlMember dirProperty, XamlScannerNode node) + { + node.PropertyElement = dirProperty; + + // node.Type is not set so any found attributes are and error. + // We don't want to skip them silently. + PostprocessAttributes(node); + + if (_scannerStack.Depth > 0) + { + // A property Element tag will be the end of content. + _scannerStack.CurrentlyInContent = false; + } + + if (!node.IsEmptyTag) + { + _scannerStack.CurrentProperty = node.PropertyElement; + } + node.NodeType = ScannerNodeType.PROPERTYELEMENT; + node.IsCtorForcingMember = false; + } + + private bool ReadObjectElement_Object(string xmlns, string name, XamlScannerNode node) + { + if (IsXDataElement(xmlns, name)) + { + // If XData don't Enqueue the node. + // just queue the InnerXml as TEXT (w/ IsTextXML == true). + // This will advance the "current" xml node to the + // which will be skipped when we return and the main loop + // Read()s to the "next" XmlNode. + ReadInnerXDataSection(); + return true; + } + + IList typeArgs = null; + if (_typeArgumentAttribute != null) + { + string error; + typeArgs = XamlTypeName.ParseListInternal(_typeArgumentAttribute.Value, _parserContext.FindNamespaceByPrefix, out error); + if (typeArgs == null) + { + throw new XamlParseException(_typeArgumentAttribute.LineNumber, _typeArgumentAttribute.LinePosition, error); + } + } + XamlTypeName typeName = new XamlTypeName(xmlns, name, typeArgs); + node.Type = _parserContext.GetXamlType(typeName, true); + + // Finish initializing the attributes in the context of the + // current Element. + PostprocessAttributes(node); + + if (_scannerStack.Depth > 0) + { + // Sub-elements (and Text) are the definition of Content + _scannerStack.CurrentlyInContent = true; + } + + if (!node.IsEmptyTag) + { + node.NodeType = ScannerNodeType.ELEMENT; + _scannerStack.Push(node.Type, node.TypeNamespace); + } + else + { + node.NodeType = ScannerNodeType.EMPTYELEMENT; + } + return false; + } + + private void ReadPropertyElement(XamlPropertyName name, XamlType tagType, string tagNamespace, bool isEmptyTag) + { + //