diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index ca3829e1bdf4b28472229fbd79d9c4f2c1d56b80..a372bac4978e8d15065ad5cedc023678ea4c4d31 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -60,6 +60,7 @@
 #include "v2math.h"
 #include "lltrans.h"
 #include "llmultifloater.h"
+#include "llsdutil.h"
 
 // use this to control "jumping" behavior when Ctrl-Tabbing
 const S32 TABBED_FLOATER_OFFSET = 0;
@@ -145,6 +146,16 @@ LLFloater::handle_map_t	LLFloater::sFloaterMap;
 
 LLFloaterView* gFloaterView = NULL;
 
+/*==========================================================================*|
+// DEV-38598: The fundamental problem with this operation is that it can only
+// support a subset of LLSD values. While it's plausible to compare two arrays
+// lexicographically, what strict ordering can you impose on maps?
+// (LLFloaterTOS's current key is an LLSD map.)
+
+// Of course something like this is necessary if you want to build a std::set
+// or std::map with LLSD keys. Fortunately we're getting by with other
+// container types for now.
+
 //static
 bool LLFloater::KeyCompare::compare(const LLSD& a, const LLSD& b)
 {
@@ -172,32 +183,11 @@ bool LLFloater::KeyCompare::compare(const LLSD& a, const LLSD& b)
 	else
 		return false; // no valid operation for Binary
 }
+|*==========================================================================*/
 
 bool LLFloater::KeyCompare::equate(const LLSD& a, const LLSD& b)
 {
-	if (a.type() != b.type())
-	{
-		//llerrs << "Mismatched LLSD types: (" << a << ") mismatches (" << b << ")" << llendl;
-		return false;
-	}
-	else if (a.isUndefined())
-		return true;
-	else if (a.isInteger())
-		return a.asInteger() == b.asInteger();
-	else if (a.isReal())
-		return a.asReal() == b.asReal();
-	else if (a.isString())
-		return a.asString() == b.asString();
-	else if (a.isUUID())
-		return a.asUUID() == b.asUUID();
-	else if (a.isDate())
-		return a.asDate() == b.asDate();
-	else if (a.isURI())
-		return a.asString() == b.asString(); // compare URIs as strings
-	else if (a.isBoolean())
-		return a.asBoolean() == b.asBoolean();
-	else
-		return false; // no valid operation for Binary
+	return llsd_equals(a, b);
 }
 
 //************************************
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index ee066317e049b23bae6fa6ac70837b191c5edb50..cace13939fc10e085b84078658bf4a81956a7034 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -87,12 +87,14 @@ friend class LLMultiFloater;
 public:
 	struct KeyCompare
 	{
-		static bool compare(const LLSD& a, const LLSD& b);
+//		static bool compare(const LLSD& a, const LLSD& b);
 		static bool equate(const LLSD& a, const LLSD& b);
+/*==========================================================================*|
 		bool operator()(const LLSD& a, const LLSD& b) const
 		{
 			return compare(a, b);
 		}
+|*==========================================================================*/
 	};
 	
 	enum EFloaterButtons
diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index 872f2cf1c1fdbf7e28d50167ba8f23d5ea06687b..3e302764de288453c4e2266b2469607d718fb608 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -397,7 +397,7 @@ BOOL LLDir_Win32::fileExists(const std::string &filename) const
 
 /*virtual*/ std::string LLDir_Win32::getLLPluginLauncher()
 {
-	return gDirUtilp->getLLPluginDir() + gDirUtilp->getDirDelimiter() +
+	return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() +
 		"SLPlugin.exe";
 }
 
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index cae6a79ec876691523229ae7ef05d451a2d5b7a7..3f8b8688d231698829292ff783229e76fe45e793 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1639,7 +1639,7 @@ if (WINDOWS)
         -E
         copy_if_different
         ${BUILT_SLPLUGIN}
-        ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin
+        ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
       COMMENT "Copying SLPlugin executable to the runtime folder."
       )
 
diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp
index d8aea2770fb1fc674f8c983ba189fb806f5580d7..8d2d48f1af876bf5b4de26c5e7d36a23db3aaadb 100644
--- a/indra/newview/llfloatertos.cpp
+++ b/indra/newview/llfloatertos.cpp
@@ -48,6 +48,7 @@
 #include "lluictrlfactory.h"
 #include "llvfile.h"
 #include "message.h"
+#include "llstartup.h"              // login_alert_done
 
 
 LLFloaterTOS::LLFloaterTOS(const LLSD& data)
@@ -206,6 +207,7 @@ void LLFloaterTOS::onCancel( void* userdata )
 {
 	LLFloaterTOS* self = (LLFloaterTOS*) userdata;
 	llinfos << "User disagrees with TOS." << llendl;
+	LLNotifications::instance().add("MustAgreeToLogIn", LLSD(), LLSD(), login_alert_done);
 
 	if(self->mReplyPumpName != "")
 	{
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index e56d28e0662f4c41597d4b9e27fc34b8b1ab7cea..8bf769a13211b02c24d2c633152c80d911913a40 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -50,7 +50,7 @@
 #include "llviewercontrol.h"
 #include "llurlsimstring.h"
 #include "llfloaterreg.h"
-#include "llfloatertos.h"
+#include "llnotifications.h"
 #include "llwindow.h"
 #if LL_LINUX || LL_SOLARIS
 #include "lltrans.h"
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 5576d446fa673e4852a869600193305116608107..477149194bd129e45f3dcbae961034f58567fb94 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -256,6 +256,7 @@ void release_start_screen();
 void reset_login();
 void apply_udp_blacklist(const std::string& csv);
 bool process_login_success_response();
+void transition_back_to_login_panel(const std::string& emsg);
 
 void callback_cache_name(const LLUUID& id, const std::string& firstname, const std::string& lastname, BOOL is_group)
 {
@@ -884,6 +885,18 @@ bool idle_startup()
 
 	if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState())
 	{
+		// Move the progress view in front of the UI immediately when login is performed
+		// this allows not to see main menu after Alt+Tab was pressed while login. EXT-744.
+		gViewerWindow->moveProgressViewToFront();
+
+		//reset the values that could have come in from a slurl
+		if (!gLoginHandler.getWebLoginKey().isNull())
+		{
+			gFirstname = gLoginHandler.getFirstName();
+			gLastname = gLoginHandler.getLastName();
+//			gWebLoginKey = gLoginHandler.getWebLoginKey();
+		}
+				
 		if (show_connect_box)
 		{
 			// TODO if not use viewer auth
@@ -1065,13 +1078,14 @@ bool idle_startup()
 
 	if(STATE_LOGIN_PROCESS_RESPONSE == LLStartUp::getStartupState()) 
 	{
-		bool transitionBackToLoginPanel = false;
 		std::ostringstream emsg;
+		emsg << "Login failed.\n";
 		if(LLLoginInstance::getInstance()->authFailure())
 		{
+			LL_INFOS("LLStartup") << "Login failed, LLLoginInstance::getResponse(): "
+			                      << LLLoginInstance::getInstance()->getResponse() << LL_ENDL;
 			// Still have error conditions that may need some 
 			// sort of handling.
-			emsg << "Login failed.\n";
 			std::string reason_response = LLLoginInstance::getInstance()->getResponse("reason");
 			std::string message_response = LLLoginInstance::getInstance()->getResponse("message");
 	
@@ -1109,10 +1123,20 @@ bool idle_startup()
 			}
 			else
 			{
-				transitionBackToLoginPanel = true;
+				// Don't pop up a notification in the TOS case because
+				// LLFloaterTOS::onCancel() already scolded the user.
+				if (reason_response != "tos")
+				{
+					LLSD args;
+					args["ERROR_MESSAGE"] = emsg.str();
+					LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
+					LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done);
+				}
 
 				//setup map of datetime strings to codes and slt & local time offset from utc
 				LLStringOps::setupDatetimeInfo (gPacificDaylightTime);
+				transition_back_to_login_panel(emsg.str());
+				show_connect_box = true;
 			}
 		}
 		else if(LLLoginInstance::getInstance()->authSuccess())
@@ -1125,7 +1149,12 @@ bool idle_startup()
 			}
 			else
 			{
-				transitionBackToLoginPanel = false;
+				LLSD args;
+				args["ERROR_MESSAGE"] = emsg.str();
+				LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
+				LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done);
+				transition_back_to_login_panel(emsg.str());
+				show_connect_box = true;
 			}
 		}
 		else
@@ -1138,23 +1167,6 @@ bool idle_startup()
 			set_startup_status(progress, auth_desc, auth_message);
 		}
 
-		if(transitionBackToLoginPanel)
-		{
-			if (gNoRender)
-			{
-				LL_WARNS("AppInit") << "Failed to login!" << LL_ENDL;
-				LL_WARNS("AppInit") << emsg << LL_ENDL;
-				exit(0);
-			}
-
-			// Bounce back to the login screen.
-			LLSD args;
-			args["ERROR_MESSAGE"] = emsg.str();
-			LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done);
-			reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW );
-			gSavedSettings.setBOOL("AutoLogin", FALSE);
-			show_connect_box = true;
-		}
 		return FALSE;
 	}
 
@@ -3080,3 +3092,17 @@ bool process_login_success_response()
 
 	return success;
 }
+
+void transition_back_to_login_panel(const std::string& emsg)
+{
+	if (gNoRender)
+	{
+		LL_WARNS("AppInit") << "Failed to login!" << LL_ENDL;
+		LL_WARNS("AppInit") << emsg << LL_ENDL;
+		exit(0);
+	}
+
+	// Bounce back to the login screen.
+	reset_login(); // calls LLStartUp::setStartupState( STATE_LOGIN_SHOW );
+	gSavedSettings.setBOOL("AutoLogin", FALSE);
+}
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index a84e79615907bbb5b89e41ddf2de08f0b11f390a..75db76df27e29e21943e3c30ccf98150d7addb72 100644
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -91,7 +91,7 @@ LLURLSimString LLURLSimString::sInstance;
 bool LLURLSimString::parse() { return true; }
 
 //-----------------------------------------------------------------------------
-#include "../llfloatertos.h"
+#include "llnotifications.h"
 #include "llfloaterreg.h"
 static std::string gTOSType;
 static LLEventPump * gTOSReplyPump = NULL;
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index af7c474b03959c8b9322b5b5b4f221e4e9b9e18a..d8f0e9f5d951314cc90b4ab821f263d59fb093cc 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -195,6 +195,10 @@ def construct(self):
         self.path(src='%s/secondlife-bin.exe' % self.args['configuration'], dst=self.final_exe())
 
         self.enable_crt_check()
+        # Plugin host application
+        self.path(os.path.join(os.pardir,
+                               'llplugin', 'slplugin', self.args['configuration'], "slplugin.exe"),
+                  "slplugin.exe")
         
         # need to get the llcommon.dll from the build directory as well
         if self.prefix(src=self.args['configuration'], dst=""):
@@ -234,11 +238,6 @@ def construct(self):
                 self.path("openjpeg.dll")
             self.end_prefix()
 
-        # Plugin host application
-        if self.prefix(src='../llplugin/slplugin/%s' % self.args['configuration'], dst="llplugin"):
-            self.path("slplugin.exe")
-            self.end_prefix()
-
         # Media plugins - QuickTime
         if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"):
             self.path("media_plugin_quicktime.dll")