Example #1
0
        public static StatelessResult PerformOneOff(CommandLineParser args)
        {
            // one-off command:
            // Anolis.Resourcer.exe -op:add -src:"C:\dest.exe" -type:ICONDIR -name:NAME  -lang:1033  -file:"C:\foo\icon.ico"
            // Anolis.Resourcer.exe -op:upd -src:"C:\dest.exe" -type:ICONDIR -name:NAME [-lang:1033] -file:"C:\foo\icon.ico"
            // Anolis.Resourcer.exe -op:ext -src:"C:\dest.exe" -type:ICONDIR -name:NAME  -lang:1033  -file:"C:\foo\icon.ico"
            // Anolis.Resourcer.exe -op:del -src:"C:\dest.exe" -type:ICONDIR -name:NAME [-lang:1033]

            CommandLineFlag
                operation    = args.GetFlag("op"),
                resSource    = args.GetFlag("src"),
                dataType     = args.GetFlag("type"),
                dataName     = args.GetFlag("name"),
                dataLang     = args.GetFlag("lang"),
                dataFile     = args.GetFlag("file");
            ushort dataLangN = 0;

            ///////////////////////////////////////
            // Validation

            // Individual arguments

            if (operation == null || resSource == null || dataType == null || dataName == null)
            {
                return(new StatelessResult(false, "Syntax error: not all arguments set"));
            }

            switch (operation.Argument)
            {
            case "add":
            case "upd":
            case "ext":
            case "del":
                break;

            default:
                return(new StatelessResult(
                           "Syntax error: invalid operation value, must be one of 'add', 'del', 'upd', or 'ext'."
                           ));
            }

            // resolve fileNames
            if (!string.IsNullOrEmpty(resSource.Argument))
            {
                resSource.Argument = Path.GetFullPath(resSource.Argument);
            }
            if (dataFile != null && !string.IsNullOrEmpty(dataFile.Argument))
            {
                dataFile.Argument = Path.GetFullPath(dataFile.Argument);
            }

            if (!File.Exists(resSource.Argument))
            {
                return(new StatelessResult("File not found: " + resSource.Argument));
            }

            if (dataLang != null)
            {
                var num = dataLang.Argument;

                if (!ushort.TryParse(num, out dataLangN))
                {
                    return(new StatelessResult("Syntax error: langId is not an unsigned integer less than 2^16"));
                }
            }

            // Combinations

            //////// Add
            if (operation.Argument == "add" && dataLang == null)
            {
                return(new StatelessResult("LangId not specified for add"));
            }
            if (operation.Argument == "add" && !File.Exists(dataFile.Argument))
            {
                return(new StatelessResult("File not found: " + dataFile.Argument));
            }

            //////// Update
            if (operation.Argument == "upd" && !File.Exists(dataFile.Argument))
            {
                return(new StatelessResult("File not found: " + dataFile.Argument));
            }

            //////// Extract

            //////// Delete
            if (operation.Argument != "del" && dataFile == null)
            {
                return(new StatelessResult("A file must be specified"));
            }

            ///////////////////////////////////////

            var typeId = ResourceTypeIdentifier.CreateFromString(dataType.Argument, true);
            var nameId = ResourceIdentifier.CreateFromString(dataName.Argument);
            var langId = dataLang != null ? dataLangN : ushort.MinValue;

            switch (operation.Argument)
            {
            case "del":

                return(OneOffDelete(resSource.Argument, typeId, nameId));

            case "add":

                return(OneOffAdd(resSource.Argument, typeId, nameId, langId, dataFile.Argument));

            case "upd":

                return(dataLang != null
                        ? OneOffUpdate(resSource.Argument, typeId, nameId, langId, dataFile.Argument)
                        : OneOffUpdate(resSource.Argument, typeId, nameId, dataFile.Argument));

            case "ext":

                return(OneOffExtract(resSource.Argument, typeId, nameId, langId, dataFile.Argument));
            }

            return(new StatelessResult("No valid operation specified, must be one of 'add', 'del', 'upd', or 'ext'."));
        }
Example #2
0
        protected override Boolean PatchFile(String fileName)
        {
            List <PatchResource> patchResources = new List <PatchResource>();

            foreach (PatchResourceSet set in _resourceSets)
            {
                if (EvaluatePatchResourceSet(set, fileName))
                {
                    // HACK: This just adds them together into a massive list. If the same name is mentioned it'll be overwritten several times
                    // fortunately it isnt' very expensive as only the last "final" one counts, but could do with filtering at this stage maybe?

                    patchResources.AddRange(set.Resources);
                }
                else
                {
                    Package.Log.Add(LogSeverity.Info, "Expression evaluation non-one: " + set.Condition.ExpressionString + ", did not process " + set.Resources.Count + " resources");
                }
            }

            if (patchResources.Count == 0)
            {
                Package.Log.Add(LogSeverity.Warning, "No resources to patch: " + fileName);
                return(false);
            }

            try {
                // for now, use lazy-load under all circumstances. In future analyse the Resources list to see if it's necessary or not
                // but the performance impact is minimal and it's the safest option, so keep it as it is
                using (ResourceSource source = ResourceSource.Open(fileName, false, ResourceSourceLoadMode.LazyLoadData)) {
                    List <String> tempFiles = new List <String>();

                    foreach (PatchResource res in patchResources)
                    {
                        if (res.Source.StartsWith("comp:", StringComparison.OrdinalIgnoreCase))
                        {
                            CompositedImage comp = new CompositedImage(res.Source, Package.RootDirectory);

                            DirectoryInfo packageTempDirectory = new DirectoryInfo(P.Combine(Package.RootDirectory.FullName, "Temp"));
                            if (!packageTempDirectory.Exists)
                            {
                                packageTempDirectory.Create();
                            }

                            // I think not using the *.bmp extension messes up Bitmap import
                            String tempFileName = PackageUtility.GetUnusedFileName(P.Combine(packageTempDirectory.FullName, P.GetFileName(Path) + res.Name) + ".bmp");

                            comp.Save(tempFileName, System.Drawing.Imaging.ImageFormat.Bmp);

                            res.File = tempFileName;
                            tempFiles.Add(tempFileName);
                        }
                        else
                        {
                            res.File = res.Source;
                        }

                        if (!File.Exists(res.File))
                        {
                            Package.Log.Add(LogSeverity.Error, "Data File not found: " + res.File);
                            continue;
                        }

                        ResourceTypeIdentifier typeId = ResourceTypeIdentifier.CreateFromString(res.Type, true);
                        ResourceIdentifier     nameId = ResourceIdentifier.CreateFromString(res.Name);
                        UInt16 langId = String.IsNullOrEmpty(res.Lang) ? UInt16.MaxValue : UInt16.Parse(res.Lang, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture);


                        if (langId == UInt16.MaxValue)                                // if the lang="" attribute was not specified

                        {
                            ResourceName name = source.GetName(typeId, nameId);

                            if (name == null)                              // if the specified name does not exist

                            {
                                if (res.Add)
                                {
                                    UInt16 sysLang = (UInt16)CultureInfo.InvariantCulture.LCID;

                                    ResourceData data = ResourceData.FromFileToAdd(res.File, sysLang, source);
                                    source.Add(typeId, nameId, sysLang, data);
                                }
                                else
                                {
                                    // Error

                                    String sourcePath = source.Name;

                                    Anolis.Core.Source.FileResourceSource frs = source as Anolis.Core.Source.FileResourceSource;
                                    if (frs != null)
                                    {
                                        sourcePath = frs.FileInfo.FullName;
                                    }

                                    Package.Log.Add(LogSeverity.Warning, "Resource name not found: " + sourcePath + '\\' + typeId.ToString() + '\\' + nameId.FriendlyName);
                                }
                            }
                            else
                            {
                                foreach (ResourceLang lang in name.Langs)
                                {
                                    ResourceData data = ResourceData.FromFileToUpdate(res.File, lang);
                                    lang.SwapData(data);
                                }
                            }
                        }
                        else                             // if the lang="" attribute was specified

                        {
                            ResourceLang lang = source.GetLang(typeId, nameId, langId);
                            if (lang == null)
                            {
                                ResourceData data = ResourceData.FromFileToAdd(res.File, langId, source);
                                source.Add(typeId, nameId, langId, data);
                            }
                            else
                            {
                                ResourceData data = ResourceData.FromFileToUpdate(res.File, lang);
                                lang.SwapData(data);
                            }
                        }
                    }                    //foreach

                    // note that Win32ResourceSource now recomptues the PE checksum by itself
                    source.CommitChanges();

                    foreach (String tempFile in tempFiles)
                    {
                        File.Delete(tempFile);
                    }

                    return(true);
                }                //using source
            } catch (AnolisException aex) {
                Package.Log.Add(LogSeverity.Error, "Patch Exception: " + aex.Message);

                if (File.Exists(fileName))
                {
                    File.Delete(fileName);
                }

                throw;
            }
        }