/* * Copyright (C) 2010-2013 JPEXS * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package com.jpexs.decompiler.flash.gui; import com.jpexs.decompiler.flash.Configuration; import com.jpexs.decompiler.flash.EventListener; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.Version; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.console.CommandLineArgumentParser; import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel; import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame; import com.jpexs.helpers.Cache; import com.jpexs.helpers.Helper; import com.jpexs.helpers.ProgressListener; import com.jpexs.helpers.ReReadableInputStream; import com.sun.jna.Platform; import com.sun.jna.WString; import com.sun.jna.platform.win32.Advapi32Util; import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.SHELLEXECUTEINFO; import com.sun.jna.platform.win32.Shell32; import com.sun.jna.platform.win32.Win32Exception; import com.sun.jna.platform.win32.WinReg; import com.sun.jna.platform.win32.WinReg.HKEY; import com.sun.jna.platform.win32.WinUser; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.*; import java.net.Socket; import java.net.URLDecoder; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Calendar; import java.util.Locale; import java.util.Properties; import java.util.logging.ConsoleHandler; import java.util.logging.FileHandler; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; import java.util.logging.SimpleFormatter; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.filechooser.FileFilter; /** * Main executable class * * @author JPEXS */ public class Main { public static ProxyFrame proxyFrame; public static String file; public static InputStream inputStream; public static String fileTitle; public static SWF swf; public static String version = ""; public static final String applicationName = "JPEXS Free Flash Decompiler"; public static String applicationVerName; public static final String shortApplicationName = "FFDec"; public static String shortApplicationVerName; public static final String projectPage = "http://www.free-decompiler.com/flash"; public static String updatePageStub = "http://www.free-decompiler.com/flash/update.html?currentVersion="; public static String updatePage; public static final String vendor = "JPEXS"; public static LoadingDialog loadingDialog; public static ModeFrame modeFrame; private static boolean working = false; private static TrayIcon trayIcon; private static MenuItem stopMenuItem; public static MainFrame mainFrame; private static final int UPDATE_SYSTEM_MAJOR = 1; private static final int UPDATE_SYSTEM_MINOR = 0; public static LoadFromMemoryFrame loadFromMemoryFrame; public static LoadFromCacheFrame loadFromCacheFrame; public static boolean readOnly = false; private static ErrorLogFrame errorLogFrame; public static void loadFromCache() { if (loadFromCacheFrame == null) { loadFromCacheFrame = new LoadFromCacheFrame(); } loadFromCacheFrame.setVisible(true); } public static void loadFromMemory() { if (loadFromMemoryFrame == null) { loadFromMemoryFrame = new LoadFromMemoryFrame(); } loadFromMemoryFrame.setVisible(true); } private static void loadProperties() { Properties prop = new Properties(); try { prop.load(Main.class.getResourceAsStream("/project.properties")); version = prop.getProperty("version"); applicationVerName = applicationName + " v." + version; updatePage = updatePageStub + version; shortApplicationVerName = shortApplicationName + " v." + version; } catch (IOException ex) { //ignore version = "unknown"; } } /** * Get title of the file * * @return file title */ public static String getFileTitle() { if (fileTitle != null) { return fileTitle; } return file; } public static void setSubLimiter(boolean value) { if (value) { AVM2Code.toSourceLimit = Configuration.SUBLIMITER; } else { AVM2Code.toSourceLimit = -1; } } public static boolean isWorking() { return working; } public static void showProxy() { if (proxyFrame == null) { proxyFrame = new ProxyFrame(); } proxyFrame.setVisible(true); proxyFrame.setState(Frame.NORMAL); } public static void startWork(String name) { startWork(name, -1, null); } public static void startWork(String name, int percent) { startWork(name, percent, null); } public static void startWork(String name, Runnable cancelCallback) { startWork(name, -1, cancelCallback); } public static void startWork(final String name, final int percent, final Runnable cancelCallback) { working = true; View.execInEventDispatch(new Runnable() { @Override public void run() { if (mainFrame != null) { mainFrame.setWorkStatus(name, cancelCallback); if (percent == -1) { mainFrame.hidePercent(); } else { mainFrame.setPercent(percent); } } if (loadingDialog != null) { loadingDialog.setDetail(name); if (percent == -1) { loadingDialog.hidePercent(); } else { loadingDialog.setPercent(percent); } } if (CommandLineArgumentParser.isCommandLineMode()) { System.out.println(name); } } }); } public static void stopWork() { working = false; if (mainFrame != null) { mainFrame.setWorkStatus("", null); } if (loadingDialog != null) { loadingDialog.setDetail(""); } } public static SWF parseSWF(String file) throws Exception { return parseSWF(new FileInputStream(file)); } public static SWF parseSWF(InputStream fis) throws Exception { SWF locswf; locswf = new SWF(fis, new ProgressListener() { @Override public void progress(int p) { startWork(AppStrings.translate("work.reading.swf"), p); } }, Configuration.getConfig("parallelSpeedUp", true)); locswf.addEventListener(new EventListener() { @Override public void handleEvent(String event, Object data) { if (event.equals("exporting")) { startWork((String) data); } if (event.equals("getVariables")) { startWork(AppStrings.translate("work.gettingvariables") + "..." + (String) data); } if (event.equals("deobfuscate")) { startWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data); } if (event.equals("rename")) { startWork(AppStrings.translate("work.renaming") + "..." + (String) data); } } }); //} return locswf; } public static void saveFile(String outfile) throws IOException { file = outfile; File outfileF = new File(outfile); File tmpFile = new File(outfile + ".tmp"); swf.saveTo(new FileOutputStream(tmpFile)); if (tmpFile.exists()) { if (tmpFile.length() > 0) { outfileF.delete(); if (!tmpFile.renameTo(outfileF)) { tmpFile.delete(); throw new IOException("Cannot access " + outfile); } } else { throw new IOException("Output is empty"); } } } private static class OpenFileWorker extends SwingWorker { @Override protected Object doInBackground() throws Exception { try { Main.startWork(AppStrings.translate("work.reading.swf") + "..."); swf = parseSWF(Main.inputStream); if (Main.inputStream instanceof FileInputStream) { Main.inputStream.close(); } } catch (OutOfMemoryError ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); View.showMessageDialog(null, "Cannot load SWF file. Out of memory."); loadingDialog.setVisible(false); swf = null; } catch (Exception ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); View.showMessageDialog(null, "Cannot load SWF file."); loadingDialog.setVisible(false); swf = null; } try { Main.startWork(AppStrings.translate("work.creatingwindow") + "..."); View.execInEventDispatch(new Runnable() { @Override public void run() { try{ mainFrame = new MainFrame(swf); } catch(Exception ex) { String a = ex.toString(); } if (errorState) { mainFrame.setErrorState(); } } }); } catch (Exception ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } loadingDialog.setVisible(false); View.execInEventDispatch(new Runnable() { @Override public void run() { if (mainFrame != null) { mainFrame.setVisible(true); } } }); Main.stopWork(); return true; } } public static boolean reloadSWF() { if (Main.inputStream == null) { mainFrame.setVisible(false); Helper.emptyObject(mainFrame); Cache.clearAll(); System.gc(); mainFrame = null; showModeFrame(); return true; } else { if (inputStream instanceof FileInputStream) { openFile(file); } else if (inputStream instanceof ReReadableInputStream) { try { ((ReReadableInputStream) inputStream).setPos(0); } catch (IOException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } return openFile(fileTitle, inputStream); } else if (inputStream instanceof BufferedInputStream) { try { ((BufferedInputStream) inputStream).reset(); } catch (IOException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } return openFile(fileTitle, inputStream); } return false; } } public static void reloadApp() { if (loadingDialog != null) { loadingDialog.setVisible(false); loadingDialog = null; } if (proxyFrame != null) { proxyFrame.setVisible(false); proxyFrame = null; } if (loadFromMemoryFrame != null) { loadFromMemoryFrame.setVisible(false); loadFromMemoryFrame = null; } if (loadFromCacheFrame != null) { loadFromCacheFrame.setVisible(false); loadFromCacheFrame = null; } reloadSWF(); } public static boolean openFile(String swfFile) { try { boolean ok = openFile(swfFile, new FileInputStream(swfFile)); if (ok) { readOnly = false; } return ok; } catch (IOException ex) { View.showMessageDialog(null, "Cannot open file", "Error", JOptionPane.ERROR_MESSAGE); } return false; } public static boolean openFile(String fileTitle, InputStream is) { Main.file = fileTitle; Main.inputStream = is; Main.fileTitle = fileTitle; readOnly = true; if (mainFrame != null) { mainFrame.setVisible(false); Helper.emptyObject(mainFrame); swf = null; mainFrame = null; Cache.clearAll(); System.gc(); } View.execInEventDispatch(new Runnable() { @Override public void run() { if (Main.loadingDialog == null) { Main.loadingDialog = new LoadingDialog(); } } }); Main.loadingDialog.setVisible(true); OpenFileWorker wrk = new OpenFileWorker(); wrk.execute(); return true; } public static boolean saveFileDialog() { JFileChooser fc = new JFileChooser(); fc.setCurrentDirectory(new File(Configuration.getConfig("lastSaveDir", "."))); FileFilter swfFilter = new FileFilter() { @Override public boolean accept(File f) { return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory()); } @Override public String getDescription() { return AppStrings.translate("filter.swf"); } }; if (!swf.gfx) { fc.setFileFilter(swfFilter); } else { fc.addChoosableFileFilter(swfFilter); } FileFilter gfxFilter = new FileFilter() { @Override public boolean accept(File f) { return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory()); } @Override public String getDescription() { return AppStrings.translate("filter.gfx"); } }; if (swf.gfx) { fc.setFileFilter(gfxFilter); } else { fc.addChoosableFileFilter(gfxFilter); } fc.setAcceptAllFileFilterUsed(false); JFrame f = new JFrame(); View.setWindowIcon(f); int returnVal = fc.showSaveDialog(f); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = Helper.fixDialogFile(fc.getSelectedFile()); FileFilter selFilter = fc.getFileFilter(); try { String fileName = file.getAbsolutePath(); if (selFilter == swfFilter) { if (!fileName.toLowerCase().endsWith(".swf")) { fileName += ".swf"; } swf.gfx = false; } if (selFilter == gfxFilter) { if (!fileName.toLowerCase().endsWith(".gfx")) { fileName += ".gfx"; } swf.gfx = true; } Main.saveFile(fileName); Configuration.setConfig("lastSaveDir", file.getParentFile().getAbsolutePath()); fileTitle = null; readOnly = false; return true; } catch (IOException ex) { View.showMessageDialog(null, AppStrings.translate("error.file.write")); } } return false; } public static boolean openFileDialog() { fileTitle = null; JFileChooser fc = new JFileChooser(); fc.setCurrentDirectory(new File(Configuration.getConfig("lastOpenDir", "."))); FileFilter allSupportedFilter = new FileFilter() { @Override public boolean accept(File f) { return (f.getName().toLowerCase().toLowerCase().endsWith(".swf")) || (f.getName().toLowerCase().toLowerCase().endsWith(".gfx")) || (f.isDirectory()); } @Override public String getDescription() { return AppStrings.translate("filter.supported"); } }; fc.setFileFilter(allSupportedFilter); FileFilter swfFilter = new FileFilter() { @Override public boolean accept(File f) { return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory()); } @Override public String getDescription() { return AppStrings.translate("filter.swf"); } }; fc.addChoosableFileFilter(swfFilter); FileFilter gfxFilter = new FileFilter() { @Override public boolean accept(File f) { return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory()); } @Override public String getDescription() { return AppStrings.translate("filter.gfx"); } }; fc.addChoosableFileFilter(gfxFilter); fc.setAcceptAllFileFilterUsed(true); JFrame f = new JFrame(); View.setWindowIcon(f); int returnVal = fc.showOpenDialog(f); if (returnVal == JFileChooser.APPROVE_OPTION) { Configuration.setConfig("lastOpenDir", Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath()); File selfile = Helper.fixDialogFile(fc.getSelectedFile()); Main.openFile(selfile.getAbsolutePath()); return true; } else { return false; } } public static void displayErrorFrame() { if (errorLogFrame != null) { errorLogFrame.setVisible(true); } } private static boolean errorState = false; private static void initGui() { View.execInEventDispatch(new Runnable() { @Override public void run() { if (errorLogFrame == null) { errorLogFrame = new ErrorLogFrame(); } Logger logger = Logger.getLogger(""); logger.addHandler(errorLogFrame.getHandler()); logger.addHandler(new Handler() { @Override public void publish(final LogRecord record) { View.execInEventDispatch(new Runnable() { @Override public void run() { if (record.getLevel() == Level.SEVERE) { errorState = true; if (mainFrame != null) { mainFrame.setErrorState(); } } } }); } @Override public void flush() { } @Override public void close() throws SecurityException { } }); } }); autoCheckForUpdates(); offerAssociation(); } public static void showModeFrame() { View.execInEventDispatch(new Runnable() { @Override public void run() { if (mainFrame == null) { mainFrame = new MainFrame(null); if (errorState) { mainFrame.setErrorState(); } } mainFrame.setVisible(true); } }); } public static void updateLicense() { updateLicenseInDir(new File(".\\src\\")); } /** * Script for updating license header in java files :-) * * @param dir Star directory (e.g. "src/") */ public static void updateLicenseInDir(File dir) { int defaultStartYear = 2010; int defaultFinalYear = 2013; String defaultAuthor = "JPEXS"; String defaultYearStr = "" + defaultStartYear; if (defaultFinalYear != defaultStartYear) { defaultYearStr += "-" + defaultFinalYear; } String license = "/*\r\n * Copyright (C) {year} {author}\r\n * \r\n * This program is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n * \r\n * This program is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n * GNU General Public License for more details.\r\n * \r\n * You should have received a copy of the GNU General Public License\r\n * along with this program. If not, see .\r\n */"; File[] files = dir.listFiles(); for (File f : files) { if (f.isDirectory()) { updateLicenseInDir(f); } else { if (f.getName().endsWith(".java")) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintWriter pw = null; try { pw = new PrintWriter(new OutputStreamWriter(baos, "utf8")); } catch (UnsupportedEncodingException ex) { } try { try (BufferedReader br = new BufferedReader(new FileReader(f))) { String s; boolean packageFound = false; String author = defaultAuthor; String yearStr = defaultYearStr; while ((s = br.readLine()) != null) { if (!packageFound) { if (s.trim().startsWith("package")) { packageFound = true; pw.println(license.replace("{year}", yearStr).replace("{author}", author)); } else { Matcher mAuthor = Pattern.compile("^.*Copyright \\(C\\) ([0-9]+)(-[0-9]+)? (.*)$").matcher(s); if (mAuthor.matches()) { author = mAuthor.group(3).trim(); int startYear = Integer.parseInt(mAuthor.group(1).trim()); if (startYear == defaultFinalYear) { yearStr = "" + startYear; } else { yearStr = "" + startYear + "-" + defaultFinalYear; } if (!author.equals(defaultAuthor)) { System.out.println("Detected nodefault author:" + author + " in " + f.getAbsolutePath()); } } } } if (packageFound) { pw.println(s); } } } pw.close(); } catch (IOException ex) { } FileOutputStream fos; try { fos = new FileOutputStream(f); fos.write(baos.toByteArray()); fos.close(); } catch (IOException ex) { } } } } } private static void offerAssociation() { boolean offered = Configuration.getConfig("offeredAssociation"); if (!offered) { if (Platform.isWindows()) { if ((!isAddedToContextMenu()) && View.showConfirmDialog(null, "Do you want to add FFDec to context menu of SWF files?\n(Can be changed later from main menu)", "Context menu", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) { addToContextMenu(true); } } } Configuration.setConfig("offeredAssociation", true); } public static void initLang() { if (Configuration.containsConfig("locale")) { Locale.setDefault(Locale.forLanguageTag(Configuration.getConfig("locale", "en"))); } UIManager.put("OptionPane.okButtonText", AppStrings.translate("button.ok")); UIManager.put("OptionPane.yesButtonText", AppStrings.translate("button.yes")); UIManager.put("OptionPane.noButtonText", AppStrings.translate("button.no")); UIManager.put("OptionPane.cancelButtonText", AppStrings.translate("button.cancel")); UIManager.put("OptionPane.messageDialogTitle", AppStrings.translate("dialog.message.title")); UIManager.put("OptionPane.titleText", AppStrings.translate("dialog.select.title")); UIManager.put("FileChooser.acceptAllFileFilterText", AppStrings.translate("FileChooser.acceptAllFileFilterText")); UIManager.put("FileChooser.lookInLabelText", AppStrings.translate("FileChooser.lookInLabelText")); UIManager.put("FileChooser.cancelButtonText", AppStrings.translate("button.cancel")); UIManager.put("FileChooser.cancelButtonToolTipText", AppStrings.translate("button.cancel")); UIManager.put("FileChooser.openButtonText", AppStrings.translate("FileChooser.openButtonText")); UIManager.put("FileChooser.openButtonToolTipText", AppStrings.translate("FileChooser.openButtonToolTipText")); UIManager.put("FileChooser.filesOfTypeLabelText", AppStrings.translate("FileChooser.filesOfTypeLabelText")); UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText")); UIManager.put("FileChooser.listViewButtonToolTipText", AppStrings.translate("FileChooser.listViewButtonToolTipText")); UIManager.put("FileChooser.listViewButtonAccessibleName", AppStrings.translate("FileChooser.listViewButtonAccessibleName")); UIManager.put("FileChooser.detailsViewButtonToolTipText", AppStrings.translate("FileChooser.detailsViewButtonToolTipText")); UIManager.put("FileChooser.detailsViewButtonAccessibleName", AppStrings.translate("FileChooser.detailsViewButtonAccessibleName")); UIManager.put("FileChooser.upFolderToolTipText", AppStrings.translate("FileChooser.upFolderToolTipText")); UIManager.put("FileChooser.upFolderAccessibleName", AppStrings.translate("FileChooser.upFolderAccessibleName")); UIManager.put("FileChooser.homeFolderToolTipText", AppStrings.translate("FileChooser.homeFolderToolTipText")); UIManager.put("FileChooser.homeFolderAccessibleName", AppStrings.translate("FileChooser.homeFolderAccessibleName")); UIManager.put("FileChooser.fileNameHeaderText", AppStrings.translate("FileChooser.fileNameHeaderText")); UIManager.put("FileChooser.fileSizeHeaderText", AppStrings.translate("FileChooser.fileSizeHeaderText")); UIManager.put("FileChooser.fileTypeHeaderText", AppStrings.translate("FileChooser.fileTypeHeaderText")); UIManager.put("FileChooser.fileDateHeaderText", AppStrings.translate("FileChooser.fileDateHeaderText")); UIManager.put("FileChooser.fileAttrHeaderText", AppStrings.translate("FileChooser.fileAttrHeaderText")); UIManager.put("FileChooser.openDialogTitleText", AppStrings.translate("FileChooser.openDialogTitleText")); UIManager.put("FileChooser.directoryDescriptionText", AppStrings.translate("FileChooser.directoryDescriptionText")); UIManager.put("FileChooser.directoryOpenButtonText", AppStrings.translate("FileChooser.directoryOpenButtonText")); UIManager.put("FileChooser.directoryOpenButtonToolTipText", AppStrings.translate("FileChooser.directoryOpenButtonToolTipText")); UIManager.put("FileChooser.fileDescriptionText", AppStrings.translate("FileChooser.fileDescriptionText")); UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText")); UIManager.put("FileChooser.helpButtonText", AppStrings.translate("FileChooser.helpButtonText")); UIManager.put("FileChooser.helpButtonToolTipText", AppStrings.translate("FileChooser.helpButtonToolTipText")); UIManager.put("FileChooser.newFolderAccessibleName", AppStrings.translate("FileChooser.newFolderAccessibleName")); UIManager.put("FileChooser.newFolderErrorText", AppStrings.translate("FileChooser.newFolderErrorText")); UIManager.put("FileChooser.newFolderToolTipText", AppStrings.translate("FileChooser.newFolderToolTipText")); UIManager.put("FileChooser.other.newFolder", AppStrings.translate("FileChooser.other.newFolder")); UIManager.put("FileChooser.other.newFolder.subsequent", AppStrings.translate("FileChooser.other.newFolder.subsequent")); UIManager.put("FileChooser.win32.newFolder", AppStrings.translate("FileChooser.win32.newFolder")); UIManager.put("FileChooser.win32.newFolder.subsequent", AppStrings.translate("FileChooser.win32.newFolder.subsequent")); UIManager.put("FileChooser.saveButtonText", AppStrings.translate("FileChooser.saveButtonText")); UIManager.put("FileChooser.saveButtonToolTipText", AppStrings.translate("FileChooser.saveButtonToolTipText")); UIManager.put("FileChooser.saveDialogTitleText", AppStrings.translate("FileChooser.saveDialogTitleText")); UIManager.put("FileChooser.saveInLabelText", AppStrings.translate("FileChooser.saveInLabelText")); UIManager.put("FileChooser.updateButtonText", AppStrings.translate("FileChooser.updateButtonText")); UIManager.put("FileChooser.updateButtonToolTipText", AppStrings.translate("FileChooser.updateButtonToolTipText")); UIManager.put("FileChooser.detailsViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewActionLabel.textAndMnemonic")); UIManager.put("FileChooser.detailsViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewButtonToolTip.textAndMnemonic")); UIManager.put("FileChooser.fileAttrHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileAttrHeader.textAndMnemonic")); UIManager.put("FileChooser.fileDateHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileDateHeader.textAndMnemonic")); UIManager.put("FileChooser.fileNameHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileNameHeader.textAndMnemonic")); UIManager.put("FileChooser.fileNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.fileNameLabel.textAndMnemonic")); UIManager.put("FileChooser.fileSizeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileSizeHeader.textAndMnemonic")); UIManager.put("FileChooser.fileTypeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileTypeHeader.textAndMnemonic")); UIManager.put("FileChooser.filesOfTypeLabel.textAndMnemonic", AppStrings.translate("FileChooser.filesOfTypeLabel.textAndMnemonic")); UIManager.put("FileChooser.folderNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.folderNameLabel.textAndMnemonic")); UIManager.put("FileChooser.homeFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.homeFolderToolTip.textAndMnemonic")); UIManager.put("FileChooser.listViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.listViewActionLabel.textAndMnemonic")); UIManager.put("FileChooser.listViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.listViewButtonToolTip.textAndMnemonic")); UIManager.put("FileChooser.lookInLabel.textAndMnemonic", AppStrings.translate("FileChooser.lookInLabel.textAndMnemonic")); UIManager.put("FileChooser.newFolderActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.newFolderActionLabel.textAndMnemonic")); UIManager.put("FileChooser.newFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.newFolderToolTip.textAndMnemonic")); UIManager.put("FileChooser.refreshActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.refreshActionLabel.textAndMnemonic")); UIManager.put("FileChooser.saveInLabel.textAndMnemonic", AppStrings.translate("FileChooser.saveInLabel.textAndMnemonic")); UIManager.put("FileChooser.upFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.upFolderToolTip.textAndMnemonic")); UIManager.put("FileChooser.viewMenuButtonAccessibleName", AppStrings.translate("FileChooser.viewMenuButtonAccessibleName")); UIManager.put("FileChooser.viewMenuButtonToolTipText", AppStrings.translate("FileChooser.viewMenuButtonToolTipText")); UIManager.put("FileChooser.viewMenuLabel.textAndMnemonic", AppStrings.translate("FileChooser.viewMenuLabel.textAndMnemonic")); UIManager.put("FileChooser.newFolderActionLabelText", AppStrings.translate("FileChooser.newFolderActionLabelText")); UIManager.put("FileChooser.listViewActionLabelText", AppStrings.translate("FileChooser.listViewActionLabelText")); UIManager.put("FileChooser.detailsViewActionLabelText", AppStrings.translate("FileChooser.detailsViewActionLabelText")); UIManager.put("FileChooser.refreshActionLabelText", AppStrings.translate("FileChooser.refreshActionLabelText")); UIManager.put("FileChooser.sortMenuLabelText", AppStrings.translate("FileChooser.sortMenuLabelText")); UIManager.put("FileChooser.viewMenuLabelText", AppStrings.translate("FileChooser.viewMenuLabelText")); UIManager.put("FileChooser.fileSizeKiloBytes", AppStrings.translate("FileChooser.fileSizeKiloBytes")); UIManager.put("FileChooser.fileSizeMegaBytes", AppStrings.translate("FileChooser.fileSizeMegaBytes")); UIManager.put("FileChooser.fileSizeGigaBytes", AppStrings.translate("FileChooser.fileSizeGigaBytes")); UIManager.put("FileChooser.folderNameLabelText", AppStrings.translate("FileChooser.folderNameLabelText")); UIManager.put("ColorChooser.okText", AppStrings.translate("ColorChooser.okText")); UIManager.put("ColorChooser.cancelText", AppStrings.translate("ColorChooser.cancelText")); UIManager.put("ColorChooser.resetText", AppStrings.translate("ColorChooser.resetText")); UIManager.put("ColorChooser.previewText", AppStrings.translate("ColorChooser.previewText")); UIManager.put("ColorChooser.swatchesNameText", AppStrings.translate("ColorChooser.swatchesNameText")); UIManager.put("ColorChooser.swatchesRecentText", AppStrings.translate("ColorChooser.swatchesRecentText")); UIManager.put("ColorChooser.sampleText", AppStrings.translate("ColorChooser.sampleText")); } /** * This may help to free some memory when not needed (maybe?) */ private static void startFreeMemThread() { new Thread() { @Override public void run() { try { while (true) { Thread.sleep(5000); System.gc(); } } catch (InterruptedException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } } }.start(); } /** * @param args the command line arguments * @throws IOException */ public static void main(String[] args) throws IOException { startFreeMemThread(); loadProperties(); Configuration.loadFromFile(getConfigFile(), getReplacementsFile()); initLogging(Configuration.debugMode); initLang(); View.setLookAndFeel(); if (Configuration.getConfig("cacheOnDisk", true)) { Cache.setStorageType(Cache.STORAGE_FILES); } else { Cache.setStorageType(Cache.STORAGE_MEMORY); } if (args.length == 0) { initGui(); showModeFrame(); } else { String fileToOpen = CommandLineArgumentParser.parseArguments(args); if (fileToOpen != null) { initGui(); openFile(fileToOpen); } } } public static String tempFile(String url) throws IOException { File f = new File(getFFDecHome() + "saved" + File.separator); if (!f.exists()) { if (!f.mkdirs()) { if (!f.exists()) { throw new IOException("cannot create directory " + f); } } } return getFFDecHome() + "saved" + File.separator + "asdec_" + Integer.toHexString(url.hashCode()) + ".tmp"; } public static void removeTrayIcon() { if (SystemTray.isSupported()) { SystemTray tray = SystemTray.getSystemTray(); if (trayIcon != null) { tray.remove(trayIcon); trayIcon = null; } } } public static void switchProxy() { proxyFrame.switchState(); if (stopMenuItem != null) { if (proxyFrame.isRunning()) { stopMenuItem.setLabel(AppStrings.translate("proxy.stop")); } else { stopMenuItem.setLabel(AppStrings.translate("proxy.start")); } } } public static void addTrayIcon() { if (trayIcon != null) { return; } if (SystemTray.isSupported()) { SystemTray tray = SystemTray.getSystemTray(); trayIcon = new TrayIcon(View.loadImage("proxy16"), vendor + " " + shortApplicationName + " " + AppStrings.translate("proxy")); trayIcon.setImageAutoSize(true); PopupMenu trayPopup = new PopupMenu(); ActionListener trayListener = new ActionListener() { /** * Invoked when an action occurs. */ @Override public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("EXIT")) { Main.exit(); } if (e.getActionCommand().equals("SHOW")) { Main.showProxy(); } if (e.getActionCommand().equals("SWITCH")) { Main.switchProxy(); } } }; MenuItem showMenuItem = new MenuItem(AppStrings.translate("proxy.show")); showMenuItem.setActionCommand("SHOW"); showMenuItem.addActionListener(trayListener); trayPopup.add(showMenuItem); stopMenuItem = new MenuItem(AppStrings.translate("proxy.start")); stopMenuItem.setActionCommand("SWITCH"); stopMenuItem.addActionListener(trayListener); trayPopup.add(stopMenuItem); trayPopup.addSeparator(); MenuItem exitMenuItem = new MenuItem(AppStrings.translate("exit")); exitMenuItem.setActionCommand("EXIT"); exitMenuItem.addActionListener(trayListener); trayPopup.add(exitMenuItem); trayIcon.setPopupMenu(trayPopup); trayIcon.addMouseListener(new MouseAdapter() { /** * {@inheritDoc} */ @Override public void mouseClicked(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1) { Main.showProxy(); } } }); try { tray.add(trayIcon); } catch (AWTException ex) { } } } public static void saveConfig() { try { Configuration.saveToFile(getConfigFile(), getReplacementsFile()); } catch (IOException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } } public static void exit() { saveConfig(); FlashPlayerPanel.unload(); System.exit(0); } public static void about() { (new AboutDialog()).setVisible(true); } public static void advancedSettings() { (new AdvancedSettingsDialog()).setVisible(true); } public static void autoCheckForUpdates() { Calendar lastUpdatesCheckDate = Configuration.getConfig("lastUpdatesCheckDate", null); if ((lastUpdatesCheckDate == null) || (lastUpdatesCheckDate.getTime().getTime() < Calendar.getInstance().getTime().getTime() - 1000 * 60 * 60 * 24)) { checkForUpdates(); } } public static boolean checkForUpdates() { try { Socket sock = new Socket("www.free-decompiler.com", 80); OutputStream os = sock.getOutputStream(); os.write(("GET /flash/update.html?action=check¤tVersion=" + version + " HTTP/1.1\r\nHost: www.free-decompiler.com\r\nUser-Agent: " + shortApplicationVerName + "\r\nConnection: close\r\n\r\n").getBytes()); BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream())); String s; boolean start = false; java.util.List versions = new ArrayList<>(); String header = ""; Pattern headerPat = Pattern.compile("\\[([a-zA-Z0-9]+)\\]"); int updateMajor = 0; int updateMinor = 0; Version ver = null; while ((s = br.readLine()) != null) { if (start) { Matcher m = headerPat.matcher(s); if (m.matches()) { header = m.group(1); if (header.equals("version")) { ver = new Version(); versions.add(ver); } if (header.equals("noversion")) { break; } } else { if (s.contains("=")) { String key = s.substring(0, s.indexOf("=")); String val = s.substring(s.indexOf("=") + 1); if ("updateSystem".equals(header)) { if (key.equals("majorVersion")) { updateMajor = Integer.parseInt(val); if (updateMajor > UPDATE_SYSTEM_MAJOR) { break; } } if (key.equals("minorVersion")) { updateMinor = Integer.parseInt(val); } } if ("version".equals(header) && (ver != null)) { if (key.equals("versionId")) { ver.versionId = Integer.parseInt(val); } if (key.equals("versionName")) { ver.versionName = val; } if (key.equals("longVersionName")) { ver.longVersionName = val; } if (key.equals("releaseDate")) { ver.releaseDate = val; } if (key.equals("appName")) { ver.appName = val; } if (key.equals("appFullName")) { ver.appFullName = val; } if (key.equals("updateLink")) { ver.updateLink = val; } if (key.equals("change[]")) { String changeType = val.substring(0, val.indexOf("|")); String change = val.substring(val.indexOf("|") + 1); if (!ver.changes.containsKey(changeType)) { ver.changes.put(changeType, new ArrayList()); } java.util.List chlist = ver.changes.get(changeType); chlist.add(change); } } } } } if (s.equals("")) { start = true; } } if (!versions.isEmpty()) { NewVersionDialog newVersionDialog = new NewVersionDialog(versions); newVersionDialog.setVisible(true); Configuration.setConfig("lastUpdatesCheckDate", Calendar.getInstance()); return true; } } catch (Exception ex) { return false; } Configuration.setConfig("lastUpdatesCheckDate", Calendar.getInstance()); return false; } private static FileHandler fileTxt; public static void clearLogFile() { Logger logger = Logger.getLogger(""); if (fileTxt != null) { fileTxt.flush(); fileTxt.close(); logger.removeHandler(fileTxt); } try { File f = new File(getFFDecHome() + File.separator + "log.txt"); FileOutputStream fos = new FileOutputStream(f); fos.close(); } catch (IOException ex) { } try { fileTxt = new FileHandler(getFFDecHome() + File.separator + "log.txt"); } catch (IOException | SecurityException ex) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); } SimpleFormatter formatterTxt = new SimpleFormatter(); fileTxt.setFormatter(formatterTxt); logger.addHandler(fileTxt); errorState = false; if (mainFrame != null) { mainFrame.clearErrorState(); } } public static void initLogging(boolean debug) { try { Logger logger = Logger.getLogger(""); logger.setLevel(debug ? Level.CONFIG : Level.WARNING); if (debug) { ConsoleHandler conHan = new ConsoleHandler(); SimpleFormatter formatterTxt = new SimpleFormatter(); conHan.setFormatter(formatterTxt); logger.addHandler(conHan); } clearLogFile(); } catch (Exception ex) { throw new RuntimeException("Problems with creating the log files"); } } private static final String CONFIG_NAME = "config.bin"; private static final String REPLACEMENTS_NAME = "replacements.cfg"; private static final File unspecifiedFile = new File("unspecified"); private static File directory = unspecifiedFile; private enum OSId { WINDOWS, OSX, UNIX } private static OSId getOSId() { PrivilegedAction doGetOSName = new PrivilegedAction() { @Override public String run() { return System.getProperty("os.name"); } }; OSId id = OSId.UNIX; String osName = AccessController.doPrivileged(doGetOSName); if (osName != null) { if (osName.toLowerCase().startsWith("mac os x")) { id = OSId.OSX; } else if (osName.contains("Windows")) { id = OSId.WINDOWS; } } return id; } public static String getFFDecHome() throws IOException { if (directory == unspecifiedFile) { directory = null; String userHome = null; try { userHome = System.getProperty("user.home"); } catch (SecurityException ignore) { } if (userHome != null) { String applicationId = Main.shortApplicationName; OSId osId = getOSId(); if (osId == OSId.WINDOWS) { File appDataDir = null; try { String appDataEV = System.getenv("APPDATA"); if ((appDataEV != null) && (appDataEV.length() > 0)) { appDataDir = new File(appDataEV); } } catch (SecurityException ignore) { } String vendorId = Main.vendor; if ((appDataDir != null) && appDataDir.isDirectory()) { // ${APPDATA}\{vendorId}\${applicationId} String path = vendorId + "\\" + applicationId + "\\"; directory = new File(appDataDir, path); } else { // ${userHome}\Application Data\${vendorId}\${applicationId} String path = "Application Data\\" + vendorId + "\\" + applicationId + "\\"; directory = new File(userHome, path); } } else if (osId == OSId.OSX) { // ${userHome}/Library/Application Support/${applicationId} String path = "Library/Application Support/" + applicationId + "/"; directory = new File(userHome, path); } else { // ${userHome}/.${applicationId}/ String path = "." + applicationId + "/"; directory = new File(userHome, path); } } } if (!directory.exists()) { if (!directory.mkdirs()) { if (!directory.exists()) { throw new IOException("cannot create directory " + directory); } } } String ret = directory.getAbsolutePath(); if (!ret.endsWith(File.separator)) { ret += File.separator; } return ret; } private static String getReplacementsFile() throws IOException { return getFFDecHome() + REPLACEMENTS_NAME; } private static String getConfigFile() throws IOException { return getFFDecHome() + CONFIG_NAME; } public static boolean isAddedToContextMenu() { if (!Platform.isWindows()) { return false; } final HKEY REG_CLASSES_HKEY = WinReg.HKEY_LOCAL_MACHINE; final String REG_CLASSES_PATH = "Software\\Classes\\"; try { if (!Advapi32Util.registryKeyExists(REG_CLASSES_HKEY, REG_CLASSES_PATH + ".swf")) { return false; } String clsName = Advapi32Util.registryGetStringValue(REG_CLASSES_HKEY, REG_CLASSES_PATH + ".swf", ""); if (clsName == null) { return false; } return Advapi32Util.registryKeyExists(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\ffdec"); } catch (Win32Exception ex) { return false; } } public static String getAppDir() { String appDir = ""; try { appDir = new File(URLDecoder.decode(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath(), "UTF-8")).getParentFile().getAbsolutePath(); } catch (UnsupportedEncodingException ex) { Logger.getLogger(FlashPlayerPanel.class.getName()).log(Level.SEVERE, null, ex); } if (!appDir.endsWith("\\")) { appDir += "\\"; } return appDir; } public static boolean addToContextMenu(boolean add) { if (add == isAddedToContextMenu()) { return true; } final String extensions[] = new String[]{"swf", "gfx"}; final HKEY REG_CLASSES_HKEY = WinReg.HKEY_LOCAL_MACHINE; final String REG_CLASSES_PATH = "Software\\Classes\\"; String appDir = getAppDir(); String exeName = "ffdec.exe"; String verb = "ffdec"; String verbName = "Open with FFDec"; boolean exists; try { exists = Advapi32Util.registryKeyExists(REG_CLASSES_HKEY, REG_CLASSES_PATH + "Applications\\" + exeName); if ((!exists) && add) { //add Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "Applications\\" + exeName); Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "Applications\\" + exeName + "\\shell"); Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "Applications\\" + exeName + "\\shell\\open"); Advapi32Util.registrySetStringValue(REG_CLASSES_HKEY, REG_CLASSES_PATH + "Applications\\" + exeName + "\\shell\\open", "", verbName); Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "Applications\\" + exeName + "\\shell\\open\\command"); Advapi32Util.registrySetStringValue(REG_CLASSES_HKEY, REG_CLASSES_PATH + "Applications\\" + exeName + "\\shell\\open\\command", "", "\"" + appDir + exeName + "\" \"%1\""); } for (String ext : extensions) { // 1) Add to context menu of SWF if (!Advapi32Util.registryKeyExists(REG_CLASSES_HKEY, REG_CLASSES_PATH + "." + ext)) { Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "." + ext); Advapi32Util.registrySetStringValue(REG_CLASSES_HKEY, REG_CLASSES_PATH + "." + ext, "", "ShockwaveFlash.ShockwaveFlash"); } String clsName = Advapi32Util.registryGetStringValue(REG_CLASSES_HKEY, REG_CLASSES_PATH + "." + ext, ""); if (!Advapi32Util.registryKeyExists(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName)) { Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName); Advapi32Util.registrySetStringValue(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName, "", "Flash Movie"); } if (!Advapi32Util.registryKeyExists(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell")) { Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell"); } exists = Advapi32Util.registryKeyExists(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\" + verb); if ((!exists) && add) { //add Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\" + verb); Advapi32Util.registrySetStringValue(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\" + verb, "", verbName); Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\" + verb + "\\command"); Advapi32Util.registrySetStringValue(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\" + verb + "\\command", "", "\"" + appDir + exeName + "\" \"%1\""); } if (exists && (!add)) { //remove Advapi32Util.registryDeleteKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\" + verb + "\\command"); Advapi32Util.registryDeleteKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + clsName + "\\shell\\" + verb); } if (exists && (!add)) { //remove Advapi32Util.registryDeleteKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "Applications\\" + exeName + "\\shell\\open\\command"); Advapi32Util.registryDeleteKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "Applications\\" + exeName + "\\shell\\open"); Advapi32Util.registryDeleteKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "Applications\\" + exeName + "\\shell"); Advapi32Util.registryDeleteKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "Applications\\" + exeName); } //2) Add to OpenWith list String mruList = Advapi32Util.registryGetStringValue(WinReg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\." + ext + "\\OpenWithList", "MRUList"); if (mruList != null) { exists = false; char appChar = 0; for (int i = 0; i < mruList.length(); i++) { String app = Advapi32Util.registryGetStringValue(WinReg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\." + ext + "\\OpenWithList", "" + mruList.charAt(i)); if (app.equals(exeName)) { appChar = mruList.charAt(i); exists = true; break; } } if ((!exists) && add) { //add for (int c = 'a'; c <= 'z'; c++) { if (mruList.indexOf(c) == -1) { mruList += (char) c; Advapi32Util.registrySetStringValue(WinReg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\." + ext + "\\OpenWithList", "" + (char) c, exeName); Advapi32Util.registrySetStringValue(WinReg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\." + ext + "\\OpenWithList", "MRUList", mruList); break; } } } if (exists && (!add)) { //remove mruList = mruList.replace("" + appChar, ""); Advapi32Util.registrySetStringValue(WinReg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\." + ext + "\\OpenWithList", "MRUList", mruList); Advapi32Util.registryDeleteValue(WinReg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\." + ext + "\\OpenWithList", "" + appChar); } } //On some systems, file must be associated in SystemFileAssociations too if (Advapi32Util.registryKeyExists(REG_CLASSES_HKEY, REG_CLASSES_PATH + "SystemFileAssociations")) { exists = Advapi32Util.registryKeyExists(REG_CLASSES_HKEY, REG_CLASSES_PATH + "SystemFileAssociations\\." + ext + "\\Shell\\" + verb); if ((!exists) && add) { //add if (!Advapi32Util.registryKeyExists(REG_CLASSES_HKEY, REG_CLASSES_PATH + "SystemFileAssociations\\." + ext + "")) { Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "SystemFileAssociations\\." + ext + ""); } if (!Advapi32Util.registryKeyExists(REG_CLASSES_HKEY, REG_CLASSES_PATH + "SystemFileAssociations\\." + ext + "\\Shell")) { Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "SystemFileAssociations\\." + ext + "\\Shell"); } Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "SystemFileAssociations\\." + ext + "\\Shell\\" + verb); Advapi32Util.registrySetStringValue(REG_CLASSES_HKEY, REG_CLASSES_PATH + "SystemFileAssociations\\." + ext + "\\Shell\\" + verb, "", verbName); Advapi32Util.registryCreateKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "SystemFileAssociations\\." + ext + "\\Shell\\" + verb + "\\Command"); Advapi32Util.registrySetStringValue(REG_CLASSES_HKEY, REG_CLASSES_PATH + "SystemFileAssociations\\." + ext + "\\Shell\\" + verb + "\\Command", "", "\"" + appDir + exeName + "\" \"%1\""); } if (exists && (!add)) { //remove Advapi32Util.registryDeleteKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "SystemFileAssociations\\." + ext + "\\Shell\\" + verb + "\\Command"); Advapi32Util.registryDeleteKey(REG_CLASSES_HKEY, REG_CLASSES_PATH + "SystemFileAssociations\\." + ext + "\\Shell\\" + verb); } } } return true; } catch (Exception ex) { //Updating registry failed, try elevating rights SHELLEXECUTEINFO sei = new SHELLEXECUTEINFO(); sei.fMask = 0x00000040; sei.lpVerb = new WString("runas"); sei.lpFile = new WString(appDir + exeName); sei.lpParameters = new WString(add ? "-addtocontextmenu" : "-removefromcontextmenu"); sei.nShow = WinUser.SW_NORMAL; Shell32.INSTANCE.ShellExecuteEx(sei); //Wait till exit Kernel32.INSTANCE.WaitForSingleObject(sei.hProcess, 1000 * 60 * 60 * 24 /*1 day max*/); } return false; } }