text: /*
  Dazzle.js:
      Usage:
              Dazzle.js [-e env_templ.xml] [-man buildmanager Identity] [-m macros_file]
  
  Get a list of machines
  
  For each machine
      create an alias for each depot on the machine, except root.
  
      BC1 jporkka1\bldcon1 _x86 _fre _x86fre _postbuild _root _inetsrv
      BC2 jporkka1\bldcon2 _x86 _fre _x86fre _ds _sdktools
      BC3 jporkka1\bldcon3 _x86 _fre _x86fre  _termsrv
  
  
      */
  
  var DEFAULT_IDENTITY_BM = "BuildManager";
  var DEFAULT_IDENTITY_BUILDER = "Build";
  
  Error.prototype.toString = Error_ToString;
  var g_FSObj              = new ActiveXObject("Scripting.FileSystemObject");    // Parse input Parameter List
  var g_aBuildManagers     = new Array();
  var g_aServersFiles      = new Array();
  var g_aMacrosFiles       = new Array();
  var g_hMacrosWritten     = new Object();
  ParseArguments(WScript.Arguments);
  main();
  WScript.Quit(0);
  
  function main()
  {
      var PrivateData;
      var objFile;
      var objMacroFile;
      var i;
      var strMacroFileName;
      var strFileName;
      var strCmdLine;
  
      for(i = 0; i < g_aBuildManagers.length; ++i)
      {
          WScript.Echo("Build manager: " + g_aBuildManagers[i].strMachine + "\\" + g_aBuildManagers[i].strMachineIdentity);
          PrivateData = GetEnvironment(g_aBuildManagers[i].strMachine, g_aBuildManagers[i].strMachineIdentity);
          if (PrivateData)
          {
              strFileName = CreateConfigFileName("Servers", g_aBuildManagers[i].strMachine, g_aBuildManagers[i].strMachineIdentity);
              g_aServersFiles[g_aServersFiles.length] = strFileName;
              objFile = g_FSObj.CreateTextFile(strFileName, true);
              objFile.WriteLine("######################################################");
              objFile.WriteLine("# Servers for build manager: " + g_aBuildManagers[i].strMachine + "\\" + g_aBuildManagers[i].strMachineIdentity);
  
              if (!strMacroFileName)
              {
                  strMacroFileName = CreateConfigFileName("Macros", g_aBuildManagers[i].strMachine, g_aBuildManagers[i].strMachineIdentity);
                  objMacroFile = g_FSObj.CreateTextFile(strMacroFileName, true);
                  WriteMacro(objMacroFile, 'root', null);
                  WriteMacro(objMacroFile, 'postbuild', null);
              }
              WriteServerInfo(objFile, objMacroFile, PrivateData);
  
              objFile.Close();
          }
      }
      strCmdLine = "BCDazzle.exe ";
  
      if (objMacroFile)
      {
          objMacroFile.Close();
          strCmdLine += " -m " + strMacroFileName;
      }
  
      if (g_aServersFiles.length)
          strCmdLine += " -s " + g_aServersFiles.join(" -s ");
  
      if (g_aMacrosFiles.length)
          strCmdLine += " -m " + g_aMacrosFiles.join(" -m ");
  
      var objShell;
      objShell = WScript.CreateObject( "WScript.Shell" )
      WScript.Echo("Running " + strCmdLine);
      objShell.Run(strCmdLine, 1);
  }
  
  // macro com  ( _com )  "CD /d %sdxroot%\\com\n"
  function WriteMacro(objMacroFile, strDepotName, strDepotPath)
  {
      if (!g_hMacrosWritten[strDepotName])
      {
          g_hMacrosWritten[strDepotName] = true;
  
          objMacroFile.WriteLine('macro '
                  + strDepotName
                  + ' ( _' + strDepotName
                  + ' ) "cd /d %sdxroot%'
                  + (strDepotPath ? '\\\\' + strDepotPath : '')
                  + '\\n"');
      }
  }
  
  function CreateConfigFileName(strName, strMachine, strMachineIdentity)
  {
      var strResult =
          g_FSObj.GetSpecialFolder(2)
          + "\\"
          + strName
          + "_"
          + strMachine
          + "_"
          + strMachineIdentity
          + ".txt";
  
      return strResult;
  }
  
  function ParseArguments(Arguments)
  {
      var strArg;
      var chArg0;
      var chArg1;
      var argn;
      var objBM;
  
      for(argn = 0; argn < Arguments.length; argn++)
      {
          strArg = Arguments(argn);
          chArg0 = strArg.charAt(0);
          chArg1 = strArg.toLowerCase().slice(1);
  
          if (chArg0 != '-' && chArg0 != '/')
              Usage(1);
          else
          {
              switch(chArg1)
              {
                  case 'e':
                      if (argn + 1 < Arguments.length)
                          objBM = LoadEnvironmentTemplate(Arguments(argn + 1));
                      else
                          Usage(2);
  
                      if (!objBM)
                          Usage(3);
  
                      g_aBuildManagers[g_aBuildManagers.length] = objBM;
                      argn++;
                      break;
                  case 'man':
                      objBM = new Object;
                      if (argn + 2 < Arguments.length)
                      {
                          objBM.strMachine         = Arguments(argn + 1);
                          objBM.strMachineIdentity = Arguments(argn + 2);
                      }
                      else
                          Usage(4);
  
                      g_aBuildManagers[g_aBuildManagers.length] = objBM;
                      argn += 2;
                      break;
                  case 'm':
                      if (argn + 1 < Arguments.length)
                          g_aMacrosFiles[g_aMacrosFiles.length] = Arguments(argn + 1);
                      else
                          Usage(5);
  
                      argn++;
                      break;
                  default:
                      Usage(4);
                      break;
              }
          }
      }
  }
  
  // MyEval(expr)
  // evaluating uneval'ed objects creates a bunch of junk local variables.
  // by putting the eval call in a little subroutine, we avoid keeping those
  // locals around.
  function MyEval(expr)
  {
      try
      {
          return eval(expr);
      }
      catch(ex)
      {
          throw ex;
      }
  }
  
  function Error_ToString()
  {
      var i;
      var str = 'Exception(';
  
      /*
          Only some error messages get filled in for "ex".
          Specifically the text for disk full never seems
          to get set by functions such as CreateTextFile().
  
  
       */
      if (this.number != null && this.description == "")
      {
          switch(this.number)
          {
              case -2147024784:
                  this.description = "There is not enough space on the disk.";
                  break;
              case -2147024894:
                  this.description = "The system cannot find the file specified.";
                  break;
              case -2147023585:
                  this.description = "There are currently no logon servers available to service the logon request.";
                  break;
              case -2147023170:
                  this.description = "The remote procedure call failed.";
                  break;
              case -2147024837:
                  this.description = "An unexpected network error occurred";
                  break;
              case -2147024890:
                  this.description = "The handle is invalid.";
                  break;
              default:
                  this.description = "Error text not set for (" + this.number + ")";
                  break;
          }
      }
      for(i in this)
      {
          str += i + ": " + this[i] + " ";
      }
      return str + ")";
  }
  
  function WriteServerInfo(objFile, objMacroFile, PrivateData)
  {
      var i;
      var j;
      var strLine;
      var aMachines = PrivateData.objEnviron.Machine;
      var strDepotName;
  
      for(i = 0; i < aMachines.length; ++i)
      {
          strLine =   aMachines[i].Name
                    + " "
                    + aMachines[i].Name + "\\BldCon_" + aMachines[i].Identity
                    + " _" + PrivateData.objConfig.Options.BuildType
                    + " _" + PrivateData.objConfig.Options.Platform;
  
          if (PrivateData.objConfig.Options.Aliases)
              strLine += " " + PrivateData.objConfig.Options.Aliases;
  
          if (aMachines[i].Aliases)
              strLine += " " + aMachines[i].Aliases;
  
          if (aMachines[i].Name == PrivateData.objEnviron.BuildManager.PostBuildMachine)
              strLine += " _root _postbuild";
  
          for(j = 0; j < aMachines[i].Depot.length; ++j)
          {
              strDepotName = aMachines[i].Depot[j].toLowerCase();
              if (strDepotName != 'root')
              {
                  strLine += " _" + strDepotName;
  
                  WriteMacro(objMacroFile, strDepotName, strDepotName);
              }
          }
          objFile.WriteLine(strLine);
      }
  }
  
  function GetEnvironment(strMachineName, strIdentity)
  {
      var strMode;
      var obj;
      var PrivateData = new Object();
      try
      {
          WScript.Echo("Attempting connection to " + strMachineName + "\\" + strIdentity);
          obj = new ActiveXObject('MTScript.Proxy');
          obj.ConnectToMTScript(strMachineName, strIdentity, false);
  
          strMode = obj.Exec('getpublic', 'PublicData.strMode');
          strMode = MyEval(strMode);
          if (strMode == 'idle')
          {
              WScript.Echo(strMachineName + "\\" + strIdentity + " is currently idle");
              return null;
          }
  
          PrivateData.objConfig = obj.Exec('getpublic', 'PrivateData.objConfig');
          PrivateData.objConfig = MyEval(PrivateData.objConfig);
  
          PrivateData.objEnviron = obj.Exec('getpublic', 'PrivateData.objEnviron');
          PrivateData.objEnviron = MyEval(PrivateData.objEnviron);
  
          var result;
  
          WScript.Echo("Starting Remote Razzle Windows...");
          result = obj.Exec('remote','');
          WScript.Echo("Remote result is " + result);
          return PrivateData;
      }
      catch(ex)
      {
          WScript.Echo("CaptureLogsManager '" + strMachineName + "\\" + strIdentity + "' failed, ex=" + ex);
      }
      return null;
  }
  
  function LoadEnvironmentTemplate(strEnviroURL)
  {
      var xml = new ActiveXObject('Microsoft.XMLDOM');
      var err = new Error();
      var node;
      var objBM = new Object();
  
      fStandaloneMode = false;
  
      xml.async = false;
      // It's unlikely they have the schema file available for this template,
      // so we turn off schema validation right now. The script engine will
      // validate it when we start the build.
      xml.validateOnParse = false;
      xml.resolveExternals = false;
  
      if (!xml.load(strEnviroURL) || !xml.documentElement)
      {
          err.description = 'Error loading the environment template ' + strEnviroURL;
          err.details = xml.parseError.reason;
  
          throw(err);
      }
  
      node = xml.documentElement.selectSingleNode('BuildManager');
  
      if (!node)
      {
          err.description = 'Invalid environment template file (BuildManager tag missing): ' + strEnviroURL;
          throw(err);
      }
  
      objBM.strMachine         = node.getAttribute("Name");
      objBM.strMachineIdentity = node.getAttribute("Identity");
  
      if (!objBM.strMachine)
      {
          err.description = 'Invalid environment template file (BuildManager tag badly formatted): ' + strEnviroURL;
          throw(err);
      }
      if (!objBM.strMachineIdentity)
          objBM.strMachineIdentity = DEFAULT_IDENTITY_BM;
  
      if (objBM.strMachine.toLowerCase() == '%localmachine%' ||
          objBM.strMachine.toLowerCase() == '%remotemachine%')
      {
          err.description = 'Sorry, cannot use the local machine or remote machine templates from this script';
          throw(err);
      }
      return objBM;
  }
  
  function Usage(x)
  {
      WScript.Echo('');
      WScript.Echo('Usage: dazzle [-e env_template.xml] [-man bldmgr identity] [-m macros]');
      WScript.Echo('');
      WScript.Echo('    -e   env_template.xml : Use the specific environment template to find the build machines');
      WScript.Echo('    -man bldmgr identity  : Query "bldmgr" with "identity" for list of');
      WScript.Echo('                            build machines instead of template files.');
      WScript.Echo('    -m   macros.txt       : Load the macros file.');
      WScript.Echo('');
      WScript.Echo('    You may specify multiple -e, -man and -m options.');
      WScript.Echo('');
      WScript.Quit(1);
  }
  