Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        private static unsafe bool EnumAETE(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam)
        {
            GCHandle  handle = GCHandle.FromIntPtr(lParam);
            QueryAETE query  = (QueryAETE)handle.Target;

            if (lpszName == query.resourceID)
            {
                IntPtr hRes = UnsafeNativeMethods.FindResourceW(hModule, lpszName, lpszType);
                if (hRes == IntPtr.Zero)
                {
                    return(false);
                }

                IntPtr loadRes = UnsafeNativeMethods.LoadResource(hModule, hRes);
                if (loadRes == IntPtr.Zero)
                {
                    return(false);
                }

                IntPtr lockRes = UnsafeNativeMethods.LockResource(loadRes);
                if (lockRes == IntPtr.Zero)
                {
                    return(false);
                }

                byte *ptr     = (byte *)lockRes.ToPointer() + 2;
                short version = *(short *)ptr;
                ptr += 2;

                int major = (version & 0xff);
                int minor = ((version >> 8) & 0xff);

                short lang = *(short *)ptr;
                ptr += 2;
                short script = *(short *)ptr;
                ptr += 2;
                short suiteCount = *(short *)ptr;
                ptr += 2;
                byte *propPtr = ptr;

                int stringLength = 0;

                if (suiteCount == 1)                 // There should only be one vendor suite
                {
                    string suiteVendor = StringUtil.FromPascalString(propPtr, out stringLength);
                    propPtr += stringLength;
                    string suiteDescription = StringUtil.FromPascalString(propPtr, out stringLength);
                    propPtr += stringLength;
                    uint suiteID = *(uint *)propPtr;
                    propPtr += 4;
                    short suiteLevel = *(short *)propPtr;
                    propPtr += 2;
                    short suiteVersion = *(short *)propPtr;
                    propPtr += 2;
                    short eventCount = *(short *)propPtr;
                    propPtr += 2;

                    if (eventCount == 1)                     // There should only be one scripting event
                    {
                        string eventVendor = StringUtil.FromPascalString(propPtr, out stringLength);
                        propPtr += stringLength;
                        string eventDescription = StringUtil.FromPascalString(propPtr, out stringLength);
                        propPtr += stringLength;
                        int eventClass = *(int *)propPtr;
                        propPtr += 4;
                        int eventType = *(int *)propPtr;
                        propPtr += 4;

                        uint replyType = *(uint *)propPtr;
                        propPtr += 7;
                        byte[] bytes = new byte[4];

                        int idx = 0;
                        while (*propPtr != 0)
                        {
                            if (*propPtr != 0x27)                             // The ' char, some filters encode the #ImR parameter type as '#'ImR.
                            {
                                bytes[idx] = *propPtr;
                                idx++;
                            }
                            propPtr++;
                        }
                        propPtr++;                         // skip the second null byte

                        uint paramType = BitConverter.ToUInt32(bytes, 0);

                        short eventFlags = *(short *)propPtr;
                        propPtr += 2;
                        short paramCount = *(short *)propPtr;
                        propPtr += 2;

                        AETEEvent evnt = new AETEEvent()
                        {
                            vendor     = eventVendor,
                            desc       = eventDescription,
                            eventClass = eventClass,
                            type       = eventType,
                            replyType  = replyType,
                            paramType  = paramType,
                            flags      = eventFlags
                        };

                        if (paramCount > 0)
                        {
                            AETEParameter[] parameters = new AETEParameter[paramCount];
                            for (int p = 0; p < paramCount; p++)
                            {
                                string name = StringUtil.FromPascalString(propPtr, out stringLength);
                                propPtr += stringLength;

                                uint key = *(uint *)propPtr;
                                propPtr += 4;

                                uint type = *(uint *)propPtr;
                                propPtr += 4;

                                string description = StringUtil.FromPascalString(propPtr, out stringLength);
                                propPtr += stringLength;

                                short parameterFlags = *(short *)propPtr;
                                propPtr += 2;

                                parameters[p] = new AETEParameter(name, key, type, description, parameterFlags);
                            }
                            evnt.parameters = parameters;
                        }

                        short classCount = *(short *)propPtr;
                        propPtr += 2;
                        if (classCount == 0)
                        {
                            short compOps = *(short *)propPtr;
                            propPtr += 2;
                            short enumCount = *(short *)propPtr;
                            propPtr += 2;
                            if (enumCount > 0)
                            {
                                AETEEnums[] enums = new AETEEnums[enumCount];
                                for (int enc = 0; enc < enumCount; enc++)
                                {
                                    uint type = *(uint *)propPtr;
                                    propPtr += 4;
                                    short count = *(short *)propPtr;
                                    propPtr += 2;

                                    AETEEnum[] values = new AETEEnum[count];

                                    for (int e = 0; e < count; e++)
                                    {
                                        string name = StringUtil.FromPascalString(propPtr, out stringLength);
                                        propPtr += stringLength;

                                        uint key = *(uint *)propPtr;
                                        propPtr += 4;

                                        string description = StringUtil.FromPascalString(propPtr, out stringLength);
                                        propPtr += stringLength;

                                        values[e] = new AETEEnum(name, key, description);
                                    }
                                    enums[enc] = new AETEEnums(type, count, values);
                                }
                                evnt.enums = enums;
                            }
                        }

                        if (evnt.parameters != null &&
                            major == PSConstants.AETEMajorVersion &&
                            minor == PSConstants.AETEMinorVersion &&
                            suiteLevel == PSConstants.AETESuiteLevel &&
                            suiteVersion == PSConstants.AETESuiteVersion)
                        {
                            query.enumAETE = new PluginAETE(major, minor, suiteLevel, suiteVersion, evnt);
                            handle.Target  = query;
                            lParam         = GCHandle.ToIntPtr(handle);
                        }
                    }
                }

                return(false);
            }

            return(true);
        }