private static unsafe bool EnumPiPL(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam) { GCHandle handle = GCHandle.FromIntPtr(lParam); QueryFilter query = (QueryFilter)handle.Target; IntPtr hRes = UnsafeNativeMethods.FindResourceW(hModule, lpszName, lpszType); if (hRes == IntPtr.Zero) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("FindResource failed for PiPL in {0}", query.fileName)); #endif return(true); } IntPtr loadRes = UnsafeNativeMethods.LoadResource(hModule, hRes); if (loadRes == IntPtr.Zero) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("LoadResource failed for PiPL in {0}", query.fileName)); #endif return(true); } IntPtr lockRes = UnsafeNativeMethods.LockResource(loadRes); if (lockRes == IntPtr.Zero) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("LockResource failed for PiPL in {0}", query.fileName)); #endif return(true); } #if DEBUG short fb = Marshal.ReadInt16(lockRes); // PiPL Resources always start with 1, this seems to be Photoshop's signature. #endif int version = Marshal.ReadInt32(lockRes, 2); if (version != PSConstants.latestPIPLVersion) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("Invalid PiPL version in {0}: {1}, Expected version {2}", query.fileName, version, PSConstants.latestPIPLVersion)); #endif return(true); } int count = Marshal.ReadInt32(lockRes, 6); byte *propPtr = (byte *)lockRes.ToPointer() + 10L; string entryPoint = null; string category = null; string title = null; FilterCaseInfo[] filterInfo = null; PluginAETE aete = null; string enableInfo = null; ushort? supportedModes = null; bool hasAboutBox = true; uint platformEntryPoint = IntPtr.Size == 8 ? PIPropertyID.PIWin64X86CodeProperty : PIPropertyID.PIWin32X86CodeProperty; for (int i = 0; i < count; i++) { PIProperty *pipp = (PIProperty *)propPtr; uint propKey = pipp->propertyKey; int propertyLength = pipp->propertyLength; byte *dataPtr = propPtr + PIProperty.SizeOf; if (propKey == PIPropertyID.PIKindProperty) { if (*((uint *)dataPtr) != PSConstants.filterKind) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("{0} is not a valid Photoshop filter.", query.fileName)); #endif return(true); } } else if (propKey == platformEntryPoint) { entryPoint = Marshal.PtrToStringAnsi((IntPtr)dataPtr, propertyLength).TrimEnd('\0'); } else if (propKey == PIPropertyID.PIVersionProperty) { int packedVersion = *(int *)dataPtr; int major = (packedVersion >> 16); int minor = (packedVersion & 0xffff); if (major > PSConstants.latestFilterVersion || major == PSConstants.latestFilterVersion && minor > PSConstants.latestFilterSubVersion) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("{0} requires newer filter interface version {1}.{2} and only version {3}.{4} is supported", new object[] { query.fileName, major, minor, PSConstants.latestFilterVersion, PSConstants.latestFilterSubVersion })); #endif return(true); } } else if (propKey == PIPropertyID.PIImageModesProperty) { #if GDIPLUS // All GDI+ images are converted to 8-bit RGB(A) for processing. if ((dataPtr[0] & PSConstants.flagSupportsRGBColor) != PSConstants.flagSupportsRGBColor) { return(true); } #else if ((dataPtr[0] & PSConstants.flagSupportsRGBColor) != PSConstants.flagSupportsRGBColor && (dataPtr[0] & PSConstants.flagSupportsGrayScale) != PSConstants.flagSupportsGrayScale) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("{0} does not support the plugInModeRGBColor or plugInModeGrayScale image modes.", query.fileName)); #endif return(true); } #endif supportedModes = *(ushort *)dataPtr; } else if (propKey == PIPropertyID.PICategoryProperty) { category = StringUtil.FromPascalString(dataPtr); } else if (propKey == PIPropertyID.PINameProperty) { title = StringUtil.FromPascalString(dataPtr); } else if (propKey == PIPropertyID.PIFilterCaseInfoProperty) { FilterCaseInfoResult result = FilterCaseInfoParser.Parse(dataPtr, propertyLength); if (result != null) { filterInfo = result.filterCaseInfo; // The actual property length may be longer than the header specifies // if the FilterCaseInfo fields are incorrectly escaped. if (propertyLength != result.propertyLength) { propertyLength = result.propertyLength; } } } else if (propKey == PIPropertyID.PIHasTerminologyProperty) { PITerminology *term = (PITerminology *)dataPtr; if (term->version == PSConstants.LatestTerminologyVersion) { #if DEBUG string aeteName = Marshal.PtrToStringAnsi(new IntPtr(dataPtr + PITerminology.SizeOf)).TrimEnd('\0'); #endif QueryAETE queryAETE = new QueryAETE(term->terminologyID); GCHandle aeteHandle = GCHandle.Alloc(queryAETE, GCHandleType.Normal); try { IntPtr callback = GCHandle.ToIntPtr(aeteHandle); if (!UnsafeNativeMethods.EnumResourceNamesW(hModule, "AETE", new UnsafeNativeMethods.EnumResNameDelegate(EnumAETE), callback)) { queryAETE = (QueryAETE)GCHandle.FromIntPtr(callback).Target; } } finally { if (aeteHandle.IsAllocated) { aeteHandle.Free(); } } if (queryAETE.enumAETE != null) { aete = queryAETE.enumAETE; } } } else if (propKey == PIPropertyID.EnableInfo) { enableInfo = Marshal.PtrToStringAnsi((IntPtr)dataPtr, propertyLength).TrimEnd('\0'); } else if (propKey == PIPropertyID.PIRequiredHostProperty) { uint host = *(uint *)dataPtr; if (host != PSConstants.kPhotoshopSignature && host != PSConstants.AnyHostSignature) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("{0} requires host '{1}'.", query.fileName, DebugUtils.PropToString(host))); #endif return(true); } } else if (propKey == PIPropertyID.NoAboutBox) { hasAboutBox = false; } #if DEBUG else { DebugUtils.Ping(DebugFlags.PiPL, string.Format("Unsupported property '{0}' in {1}", DebugUtils.PropToString(propKey), query.fileName)); } #endif // The property data is padded to a 4 byte boundary. int propertyDataPaddedLength = (propertyLength + 3) & ~3; propPtr += (PIProperty.SizeOf + propertyDataPaddedLength); } PluginData pluginData = new PluginData(query.fileName, entryPoint, category, title, filterInfo, aete, enableInfo, supportedModes, hasAboutBox); if (pluginData.IsValid()) { query.plugins.Add(pluginData); handle.Target = query; lParam = GCHandle.ToIntPtr(handle); } return(true); }
private static unsafe bool EnumPiPL(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam) { GCHandle handle = GCHandle.FromIntPtr(lParam); QueryFilter query = (QueryFilter)handle.Target; IntPtr hRes = UnsafeNativeMethods.FindResourceW(hModule, lpszName, lpszType); if (hRes == IntPtr.Zero) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("FindResource failed for PiPL in {0}", query.fileName)); #endif return(true); } IntPtr loadRes = UnsafeNativeMethods.LoadResource(hModule, hRes); if (loadRes == IntPtr.Zero) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("LoadResource failed for PiPL in {0}", query.fileName)); #endif return(true); } IntPtr lockRes = UnsafeNativeMethods.LockResource(loadRes); if (lockRes == IntPtr.Zero) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("LockResource failed for PiPL in {0}", query.fileName)); #endif return(true); } #if DEBUG short fb = Marshal.ReadInt16(lockRes); // PiPL Resources always start with 1, this seems to be Photoshop's signature #endif int version = Marshal.ReadInt32(lockRes, 2); if (version != PSConstants.LatestPiPLVersion) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("Invalid PiPL version in {0}: {1}, Expected version {2}", query.fileName, version, PSConstants.LatestPiPLVersion)); #endif return(true); } string entryPoint = null; string category = null; string title = null; FilterCaseInfoCollection filterInfo = null; AETEData aete = null; string enableInfo = null; int count = Marshal.ReadInt32(lockRes, 6); byte *propPtr = (byte *)lockRes.ToPointer() + 10; for (int i = 0; i < count; i++) { PIProperty *pipp = (PIProperty *)propPtr; if (pipp->vendorID != PSConstants.kPhotoshopSignature) { // The property data is padded to a 4 byte boundary. propPtr += PIProperty.SizeOf + ((pipp->propertyLength + 3) & ~3); continue; } uint propKey = pipp->propertyKey; int propertyLength = pipp->propertyLength; byte *dataPtr = propPtr + PIProperty.SizeOf; if (propKey == PIPropertyID.PIKindProperty) { if (*(uint *)dataPtr != PSConstants.FilterKind) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("{0} is not a valid Photoshop Filter.", query.fileName)); #endif return(true); } } else if (propKey == query.platformEntryPoint) { entryPoint = StringUtil.FromCString(dataPtr); } else if (propKey == PIPropertyID.PIVersionProperty) { int packedVersion = *(int *)dataPtr; int major = packedVersion >> 16; int minor = packedVersion & 0xffff; if (major > PSConstants.latestFilterVersion || major == PSConstants.latestFilterVersion && minor > PSConstants.latestFilterSubVersion) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("{0} requires newer filter interface version {1}.{2} and only version {3}.{4} is supported", new object[] { query.fileName, major, minor, PSConstants.latestFilterVersion, PSConstants.latestFilterSubVersion })); #endif return(true); } } else if (propKey == PIPropertyID.PIImageModesProperty) { if ((dataPtr[0] & PSConstants.flagSupportsRGBColor) != PSConstants.flagSupportsRGBColor) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("{0} does not support the plugInModeRGBColor image mode.", query.fileName)); #endif return(true); } } else if (propKey == PIPropertyID.PICategoryProperty) { category = StringUtil.FromPascalString(dataPtr); } else if (propKey == PIPropertyID.PINameProperty) { title = StringUtil.FromPascalString(dataPtr); } else if (propKey == PIPropertyID.PIFilterCaseInfoProperty) { FilterCaseInfoResult result = FilterCaseInfoParser.Parse(dataPtr, propertyLength); if (result != null) { filterInfo = result.filterCaseInfo; // The actual property length may be longer than the header specifies // if the FilterCaseInfo fields are incorrectly escaped. if (propertyLength != result.propertyLength) { propertyLength = result.propertyLength; } } } else if (propKey == PIPropertyID.PIHasTerminologyProperty) { PITerminology *term = (PITerminology *)dataPtr; if (term->version == PSConstants.LatestTerminologyVersion) { #if DEBUG string aeteName = StringUtil.FromCString(dataPtr + PITerminology.SizeOf); #endif aete = ParseAETEResource(hModule, term->terminologyID); } } else if (propKey == PIPropertyID.PIEnableInfoProperty) { enableInfo = StringUtil.FromCString(dataPtr); } else if (propKey == PIPropertyID.PIRequiredHostProperty) { uint host = *(uint *)dataPtr; if (host != PSConstants.kPhotoshopSignature && host != PSConstants.AnyHostSignature) { #if DEBUG System.Diagnostics.Debug.WriteLine(string.Format("{0} requires host '{1}'.", query.fileName, DebugUtils.PropToString(host))); #endif return(true); } } #if DEBUG else { DebugUtils.Ping(DebugFlags.PiPL, string.Format("Unsupported property '{0}' in {1}", DebugUtils.PropToString(propKey), query.fileName)); } #endif int propertyDataPaddedLength = (propertyLength + 3) & ~3; propPtr += PIProperty.SizeOf + propertyDataPaddedLength; } PluginData enumData = new PluginData(query.fileName, entryPoint, category, title, filterInfo, query.runWith32BitShim, aete, enableInfo); if (enumData.IsValid()) { query.plugins.Add(enumData); } return(true); }