diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java index 4207c37f52..d9479c5a6d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardIngestConfigPanel.java @@ -222,14 +222,14 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel CASE_EVENTS_OF_INTEREST = new HashSet<>(Arrays.asList(new String[]{Case.Events.ADDING_DATA_SOURCE.toString(), Case.Events.DATA_SOURCE_ADDED.toString()})); + private static final Set CASE_EVENTS_OF_INTEREST = new HashSet<>(Arrays.asList(new String[]{Case.Events.ADDING_DATA_SOURCE.toString(), Case.Events.DATA_SOURCE_ADDED.toString(), Case.Events.ADDING_DATA_SOURCE_FAILED.toString()})); private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 3; private static final String PERIODIC_TASK_THREAD_NAME = "collab-monitor-periodic-tasks-%d"; private static final long HEARTBEAT_INTERVAL_MINUTES = 1; @@ -77,7 +76,6 @@ final class CollaborationMonitor { private static final long STALE_TASKS_DETECTION_INTERVAL_MINUTES = 2; private static final long CRASH_DETECTION_INTERVAL_MINUTES = 2; private static final long EXECUTOR_TERMINATION_WAIT_SECS = 30; - private static final SimpleDateFormat SERVICE_MSG_DATE_FORMAT = new SimpleDateFormat("MM/dd HH:mm:ss z"); private static final Logger logger = Logger.getLogger(CollaborationMonitor.class.getName()); private final String hostName; private final LocalTasksManager localTasksManager; @@ -525,7 +523,7 @@ final class CollaborationMonitor { private final static class CrashDetectionTask implements Runnable { private static boolean dbServerIsRunning = true; -// private static boolean solrServerIsRunning = true; + private static boolean solrServerIsRunning = true; private static boolean messageServerIsRunning = true; private static final Object lock = new Object(); @@ -540,41 +538,33 @@ final class CollaborationMonitor { if (!dbServerIsRunning) { dbServerIsRunning = true; logger.log(Level.INFO, "Connection to PostgreSQL server restored"); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title", SERVICE_MSG_DATE_FORMAT.format(new Date())), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredDbService.notify.msg")); + MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredDbService.notify.msg")); } } else { if (dbServerIsRunning) { dbServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to PostgreSQL server"); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title", SERVICE_MSG_DATE_FORMAT.format(new Date())), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedDbService.notify.msg")); + MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedDbService.notify.msg")); } } - /** - * TODO: Figure out what is wrong with this code. The call to - * construct the HttpSolrServer object never returns. Perhaps - * this is the result of a dependency of the solr-solrj-4.91.jar - * that is not satisfied. Removing the jar from wrapped jars for - * now. - */ -// try { -// String host = UserPreferences.getIndexingServerHost(); -// String port = UserPreferences.getIndexingServerPort(); -// HttpSolrServer solr = new HttpSolrServer("http://" + host + ":" + port + "/solr"); //NON-NLS -// CoreAdminRequest.getStatus(Case.getCurrentCase().getTextIndexName(), solr); -// if (!solrServerIsRunning) { -// solrServerIsRunning = true; -// logger.log(Level.INFO, "Connection to Solr server restored"); //NON-NLS -// MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title", SERVICE_MSG_DATE_FORMAT.format(new Date())), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredSolrService.notify.msg")); -// } -// } catch (SolrServerException | IOException ex) { -// if (solrServerIsRunning) { -// solrServerIsRunning = false; -// logger.log(Level.SEVERE, "Failed to connect to Solr server", ex); //NON-NLS -// MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title", SERVICE_MSG_DATE_FORMAT.format(new Date())), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedSolrService.notify.msg")); -// } -// } -// + KeywordSearchService kwsService = Case.getCurrentCase().getServices().getKeywordSearchService(); + + if (kwsService.canConnectToRemoteSolrServer()) { + if (!solrServerIsRunning) { + solrServerIsRunning = true; + logger.log(Level.INFO, "Connection to Solr server restored"); //NON-NLS + MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredSolrService.notify.msg")); + } + } + else { + if (solrServerIsRunning) { + solrServerIsRunning = false; + logger.log(Level.SEVERE, "Failed to connect to Solr server"); //NON-NLS + MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedSolrService.notify.msg")); + } + } + MessageServiceConnectionInfo msgInfo = UserPreferences.getMessageServiceConnectionInfo(); try { ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(msgInfo.getUserName(), msgInfo.getPassword(), msgInfo.getURI()); @@ -584,13 +574,13 @@ final class CollaborationMonitor { if (!messageServerIsRunning) { messageServerIsRunning = true; logger.log(Level.INFO, "Connection to ActiveMQ server restored"); //NON-NLS - MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title", SERVICE_MSG_DATE_FORMAT.format(new Date())), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredMessageService.notify.msg")); + MessageNotifyUtil.Notify.info(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.restoredMessageService.notify.msg")); } } catch (URISyntaxException | JMSException ex) { if (messageServerIsRunning) { messageServerIsRunning = false; logger.log(Level.SEVERE, "Failed to connect to ActiveMQ server", ex); //NON-NLS - MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title", SERVICE_MSG_DATE_FORMAT.format(new Date())), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedMessageService.notify.msg")); + MessageNotifyUtil.Notify.error(NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedService.notify.title"), NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.failedMessageService.notify.msg")); } } } diff --git a/Core/src/org/sleuthkit/autopsy/core/Installer.java b/Core/src/org/sleuthkit/autopsy/core/Installer.java index 2a66309d4e..ecf1d0e595 100644 --- a/Core/src/org/sleuthkit/autopsy/core/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/core/Installer.java @@ -65,6 +65,7 @@ public class Installer extends ModuleInstall { //We should update this if we officially switch to a new version of CRT/compiler System.loadLibrary("msvcr100"); //NON-NLS System.loadLibrary("msvcp100"); //NON-NLS + System.loadLibrary("msvcr120"); //NON-NLS logger.log(Level.INFO, "MSVCR100 and MSVCP100 libraries loaded"); //NON-NLS } catch (UnsatisfiedLinkError e) { logger.log(Level.SEVERE, "Error loading MSVCR100 and MSVCP100 libraries, ", e); //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java index eb8da0234c..702b91f7a5 100755 --- a/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java +++ b/Core/src/org/sleuthkit/autopsy/core/UserPreferences.java @@ -115,7 +115,7 @@ public final class UserPreferences { } return new CaseDbConnectionInfo( preferences.get(EXTERNAL_DATABASE_HOSTNAME_OR_IP, ""), - preferences.get(EXTERNAL_DATABASE_PORTNUMBER, ""), + preferences.get(EXTERNAL_DATABASE_PORTNUMBER, "5432"), preferences.get(EXTERNAL_DATABASE_USER, ""), preferences.get(EXTERNAL_DATABASE_PASSWORD, ""), dbType); @@ -138,7 +138,7 @@ public final class UserPreferences { } public static String getIndexingServerPort() { - return preferences.get(INDEXING_SERVER_PORT, ""); + return preferences.get(INDEXING_SERVER_PORT, "8983"); } public static void setIndexingServerPort(int port) { @@ -166,7 +166,7 @@ public final class UserPreferences { return new MessageServiceConnectionInfo(preferences.get(MESSAGE_SERVICE_USER, ""), preferences.get(MESSAGE_SERVICE_PASSWORD, ""), preferences.get(MESSAGE_SERVICE_HOST, ""), - preferences.get(MESSAGE_SERVICE_PORT, "")); + preferences.get(MESSAGE_SERVICE_PORT, "61616")); } /** diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index e6b4262d64..e5b986e672 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -175,8 +175,6 @@ MultiUserSettingsPanel.msgPasswordField.toolTipText=Password MultiUserSettingsPanel.msgPasswordField.text= MultiUserSettingsPanel.msgPortTextField.toolTipText=Hostname or IP Address MultiUserSettingsPanel.msgPortTextField.text= -MultiUserSettingsPanel.tbIndexingServerHost.text=localhost -MultiUserSettingsPanel.tbIndexingServerPort.text=23232 MultiUserSettingsPanel.tbIndexingServerHost.toolTipText=Hostname or IP Address MultiUserSettingsPanel.tbIndexingServerPort.toolTipText=Port Number AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text= diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.form index 0b9de1eaef..32bee7c818 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.form @@ -238,9 +238,6 @@ - - - @@ -254,9 +251,6 @@ - - - diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java index 34939169c9..930b4a6b99 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/MultiUserSettingsPanel.java @@ -193,7 +193,6 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(lbSolrSettings, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbSolrSettings.text")); // NOI18N tbIndexingServerHost.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N - tbIndexingServerHost.setText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbIndexingServerHost.text")); // NOI18N tbIndexingServerHost.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbIndexingServerHost.toolTipText")); // NOI18N tbIndexingServerHost.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -202,7 +201,6 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel { }); tbIndexingServerPort.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N - tbIndexingServerPort.setText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbIndexingServerPort.text")); // NOI18N tbIndexingServerPort.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbIndexingServerPort.toolTipText")); // NOI18N tbIndexingServerPort.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/MessageNotifyUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/MessageNotifyUtil.java index 15bd89731e..8d67d94fed 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/MessageNotifyUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/MessageNotifyUtil.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013 Basis Technology Corp. + * Copyright 2013-2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,8 +20,10 @@ package org.sleuthkit.autopsy.coreutils; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.List; import java.util.logging.Level; import javax.swing.Icon; @@ -52,8 +54,8 @@ public class MessageNotifyUtil { INFO(NotifyDescriptor.INFORMATION_MESSAGE, "info-icon-16.png"), //NON-NLS ERROR(NotifyDescriptor.ERROR_MESSAGE, "error-icon-16.png"), //NON-NLS WARNING(NotifyDescriptor.WARNING_MESSAGE, "warning-icon-16.png"); //NON-NLS - private int notifyDescriptorType; - private Icon icon; + private final int notifyDescriptorType; + private final Icon icon; private MessageType(int notifyDescriptorType, String resourceName) { this.notifyDescriptorType = notifyDescriptorType; @@ -121,7 +123,7 @@ public class MessageNotifyUtil { /** * Show an error dialog * - * @param message message to shpw + * @param message message to show */ public static void error(String message) { show(message, MessageType.ERROR); @@ -142,20 +144,21 @@ public class MessageNotifyUtil { */ public static class Notify { + private static final SimpleDateFormat TIME_STAMP_FORMAT = new SimpleDateFormat("MM/dd/yy HH:mm:ss z"); + //notifications to keep track of and to reset when case is closed private static final List notifications = Collections.synchronizedList(new ArrayList()); private Notify() { } - + /** - * Clear pending notifications - * Should really only be used by Case + * Clear pending notifications Should really only be used by Case */ public static void clear() { - for (Notification n : notifications) { + notifications.stream().forEach((n) -> { n.clear(); - } + }); notifications.clear(); } @@ -163,8 +166,8 @@ public class MessageNotifyUtil { * Show message with the specified type and action listener */ public static void show(String title, String message, MessageType type, ActionListener actionListener) { - Notification newNotification = - NotificationDisplayer.getDefault().notify(title, type.getIcon(), message, actionListener); + Notification newNotification + = NotificationDisplayer.getDefault().notify(addTimeStampToTitle(title), type.getIcon(), message, actionListener); notifications.add(newNotification); } @@ -178,11 +181,8 @@ public class MessageNotifyUtil { * @param type type of the message */ public static void show(String title, final String message, final MessageType type) { - ActionListener actionListener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - MessageNotifyUtil.Message.show(message, type); - } + ActionListener actionListener = (ActionEvent e) -> { + MessageNotifyUtil.Message.show(message, type); }; show(title, message, type, actionListener); @@ -217,5 +217,17 @@ public class MessageNotifyUtil { public static void warn(String title, String message) { show(title, message, MessageType.WARNING); } + + /** + * Adds a time stamp prefix to the title of notifications so that they + * will be in order (they are sorted alphabetically) in the + * notifications area. + * + * @param title A notification title without a time stamp prefix. + * @return The notification title with a time stamp prefix. + */ + private static String addTimeStampToTitle(String title) { + return TIME_STAMP_FORMAT.format(new Date()) + " " + title; + } } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java index 47f5c61862..895aa63e06 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java @@ -343,6 +343,7 @@ final class DataSourceIngestJob { * @return A collection of ingest module startup errors, empty on success. */ List start() { + IngestManager.getInstance().fireDataSourceAnalysisStarted(parentJob.getId(), id, dataSource); List errors = startUpIngestPipelines(); if (errors.isEmpty()) { if (this.hasFirstStageDataSourceIngestPipeline() || this.hasFileIngestPipeline()) { @@ -936,7 +937,8 @@ final class DataSourceIngestJob { } } } - + + IngestManager.getInstance().fireDataSourceAnalysisCancelled(parentJob.getId(), id, dataSource); this.cancelled = true; /** diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java index 718b8a88c7..f9fdf99c5b 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJob.java @@ -116,12 +116,7 @@ public final class IngestJob { * startup is going to fail, it will likely fail for the first child * data source ingest job. */ - if (errors.isEmpty()) { - IngestManager ingestManager = IngestManager.getInstance(); - this.dataSourceJobs.values().stream().forEach((dataSourceJob) -> { - ingestManager.fireDataSourceAnalysisStarted(id, dataSourceJob.getId(), dataSourceJob.getDataSource()); - }); - } else { + if(! errors.isEmpty()) { this.dataSourceJobs.values().stream().forEach((dataSourceJob) -> { dataSourceJob.cancel(); }); @@ -172,7 +167,6 @@ public final class IngestJob { IngestManager ingestManager = IngestManager.getInstance(); this.dataSourceJobs.values().stream().forEach((job) -> { job.cancel(); - ingestManager.fireDataSourceAnalysisCancelled(id, job.getId(), job.getDataSource()); }); this.cancelled = true; } diff --git a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java index c14adbb0bb..e4c15e8721 100644 --- a/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java +++ b/Core/src/org/sleuthkit/autopsy/keywordsearchservice/KeywordSearchService.java @@ -35,4 +35,10 @@ public interface KeywordSearchService extends Closeable { * @throws org.sleuthkit.datamodel.TskCoreException */ public void indexArtifact(BlackboardArtifact artifact) throws TskCoreException; + + /** + * Are we able to connect to the remote Solr server. + * @return true if we can connect, otherwise false + */ + public boolean canConnectToRemoteSolrServer(); } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java index 2f6997be76..49a62021a0 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java @@ -984,7 +984,7 @@ public class Server { } } - private HttpSolrServer connectToRemoteSolrServer() { + HttpSolrServer connectToRemoteSolrServer() { String host = UserPreferences.getIndexingServerHost(); String port = UserPreferences.getIndexingServerPort(); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index 061a7f872d..51d2e3ebbe 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -20,11 +20,15 @@ package org.sleuthkit.autopsy.keywordsearch; import java.io.IOException; import java.util.HashMap; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.impl.HttpSolrServer; +import org.apache.solr.client.solrj.request.CoreAdminRequest; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.apache.solr.common.util.ContentStreamBase.StringStream; +import org.openide.util.Exceptions; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.datamodel.ContentUtils; @@ -145,6 +149,19 @@ public class SolrSearchService implements KeywordSearchService { } } + @Override + public boolean canConnectToRemoteSolrServer() { + try { + HttpSolrServer solrServer = KeywordSearch.getServer().connectToRemoteSolrServer(); + CoreAdminRequest.getStatus(null, solrServer); + } + catch (SolrServerException | IOException ex) { + return false; + } + + return true; + } + @Override public void close() throws IOException { } diff --git a/thirdparty/crt/update.bat b/thirdparty/crt/update.bat index fd1c6daec2..807264ff07 100644 --- a/thirdparty/crt/update.bat +++ b/thirdparty/crt/update.bat @@ -3,5 +3,7 @@ REM Needs to be run from a 64-bit command prompt REM Otherwise Windows will put 32-bit dlls in system32 copy c:\windows\system32\msvcr100.dll win64 copy c:\windows\system32\msvcp100.dll win64 +copy c:\windows\system32\msvcr120.dll win64 copy c:\windows\sysWoW64\msvcr100.dll win32 copy c:\windows\sysWow64\msvcp100.dll win32 +copy c:\windows\sysWow64\msvcr120.dll win32 diff --git a/thirdparty/crt/win64/msvcr120.dll b/thirdparty/crt/win64/msvcr120.dll new file mode 100755 index 0000000000..d711c92232 Binary files /dev/null and b/thirdparty/crt/win64/msvcr120.dll differ