/// <summary> /// Start kmod and connect to it. /// </summary> private void StartKmod() { FileStream file = null; Socket listenSock = null; RegistryKey kwmRegKey = null; try { // Get the path to the kmod executable in the registry. kwmRegKey = KwmReg.GetKwmLMRegKey(); String Kmod = "\"" + (String)kwmRegKey.GetValue("InstallDir", @"C:\Program Files\Teambox\Teambox Manager") + "\\kmod\\kmod.exe\""; // The directory where KMOD will save logs and its database for use with the kwm. String KmodDir = KwmPath.GetKmodDirPath(); Directory.CreateDirectory(KmodDir); // Start listening for kmod to connect when it'll be started. IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, 0); listenSock = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); listenSock.Bind(endPoint); listenSock.Listen(1); int port = ((IPEndPoint)listenSock.LocalEndPoint).Port; // Start KMOD in debugging mode if our settings say so. String debug = KwmCfg.Cur.KtlstunnelLoggingLevel > 0 ? " -l 3" : ""; String args = " -C kmod_connect -p " + port + debug + " -m 20000 -k \"" + KmodDir + "\""; String cmdLine = Kmod + args; KLogging.Log("About to start kmod.exe: " + cmdLine); m_kmodProc = new KProcess(cmdLine); m_kmodProc.InheritHandles = false; m_kmodProc.CreationFlags = (uint)KSyscalls.CREATION_FLAGS.CREATE_NO_WINDOW; m_kmodProc.Start(); // Wait for KMOD to connect for about 10 seconds. DateTime startTime = DateTime.Now; while (true) { SelectSockets select = new SelectSockets(); select.AddRead(listenSock); SetSelectTimeout(startTime, 10000, select, "no KMOD connection received"); Block(select); if (select.InRead(listenSock)) { m_kmodSock = listenSock.Accept(); m_kmodSock.Blocking = false; break; } } // Read the authentication data. byte[] authSockData = new byte[32]; byte[] authFileData = new byte[32]; startTime = DateTime.Now; int nbRead = 0; while (nbRead != 32) { SelectSockets select = new SelectSockets(); select.AddRead(m_kmodSock); SetSelectTimeout(startTime, 2000, select, "no authentication data received"); Block(select); int r = KSocket.SockRead(m_kmodSock, authSockData, nbRead, 32 - nbRead); if (r > 0) nbRead += r; } file = File.Open(KmodDir + "\\connect_secret", FileMode.Open); file.Read(authFileData, 0, 32); if (!KUtil.ByteArrayEqual(authFileData, authSockData)) throw new Exception("invalid authentication data received"); // Set the transport. m_transport = new K3pTransport(m_kmodSock); } finally { if (file != null) file.Close(); if (listenSock != null) listenSock.Close(); if (kwmRegKey != null) kwmRegKey.Close(); } }
/// <summary> /// Start the process specified. /// </summary> private void StartProcess(bool mainFlag) { // Kill any lingering process. if (mainFlag) { String lingeringName = ServerSessionFlag ? "kappserver" : "kappviewer"; foreach (Process l in Process.GetProcessesByName(lingeringName)) l.Kill(); } // Get the executable path and its arguments. String path = "\"" + KwmPath.GetKwmInstallationPath() + @"vnc\"; path += ServerSessionFlag ? "kappserver.exe" : "kappviewer.exe"; path += "\""; String args = ""; if (ServerSessionFlag && !mainFlag) { if (WindowHandle == 0) args = " -shareall"; else args = " -sharehwnd " + WindowHandle; } else if (!ServerSessionFlag) { args = " /shared /notoolbar /disableclipboard /encoding tight /compresslevel 9 localhost"; } // Start the process. KProcess p = new KProcess(path + args); if (mainFlag) MainProcess = p; else DummyProcess = p; p.CreationFlags = (uint)KSyscalls.CREATION_FLAGS.CREATE_NO_WINDOW; p.InheritHandles = false; KSyscalls.STARTUPINFO si = new KSyscalls.STARTUPINFO(); // I don't know why this is set. if (ServerSessionFlag) si.dwFlags = 1; p.StartupInfo = si; p.ProcessEnd += OnProcessEnd; p.Start(); // Poll the process until it starts. NbTimerEvent = 0; Timer.TimerWakeUpCallback = OnProcessPollEvent; Timer.Args = new object[] { p }; Timer.WakeMeUp(0); }
/// <summary> /// Display an error message to the user and exit the application if /// required. /// </summary> public static void HandleError(String errorMessage, bool fatalFlag) { string msg = "An error has been detected." + Environment.NewLine + Environment.NewLine + errorMessage + Environment.NewLine + Environment.NewLine; if (fatalFlag) { msg += "Please restart your " + KwmStrings.Kwm; } else { msg += "Please contact your technical support for further information."; } // Transient error. Queue the message to be displayed. if (!fatalFlag) { WmErrorMsg em = new WmErrorMsg(); em.Ex = new Exception(errorMessage); WmErrorGer ger = new WmErrorGer(em); ger.Queue(); return; } // The .Net framework is critically brain damaged when it comes to // handling fatal errors. There are basically two choices: exit // the process right away or try to get the application to display // the error and quit. // // The former choice is sane; there is no risk of further data // corruption if the process exits right away. The lack of any // error message is problematic however. We work around this by // spawning an external program, if possible, to report the error // before exiting the process. // // The second choice cannot be done sanely. If a MessageBox() // call is made immediately when the error is detected, then // the UI will be reentered and the damage may spread further. // Typically this causes multiple fatal error messages to // appear. After some investigation, I believe this is impossible // to prevent. The best available thing is ThreadAbortException, // which has weird semantics and is considered deprecated and // doesn't do the right thing in worker threads. // Exit right away. if (!FatalErrorMsgOKFlag || m_fatalErrorCaughtFlag) Environment.Exit(1); // We have caught a fatal error. Prevent the other threads from // spawning a fatal error. There is an inherent race condition // here which is best left alone; mutexes have no business here. m_fatalErrorCaughtFlag = true; // Spawn a program to display the message. try { String startupLine = '"' + Application.ExecutablePath + '"' + " "; startupLine += "\"-M\" \"" + EscapeArgForFatalError(msg) + "\""; KProcess p = new KProcess(startupLine); p.InheritHandles = false; p.Start(); } // Ignore all exceptions. catch (Exception) { } // Get out. Environment.Exit(1); }
/// <summary> /// Create a listening socket and spawn ktlstunnel process. /// </summary> public void BeginTls(string extraParams) { IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, 0); Sock = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); Sock.Bind(endPoint); Sock.Listen(1); // Create a logging dir for ktlstunnel, if it does not exist. if (!Directory.Exists(KwmPath.GetKtlstunnelLogFilePath())) { Directory.CreateDirectory(KwmPath.GetKtlstunnelLogFilePath()); } // Start ktlstunnel as such. // ktlstunnel localhost ((IPEndPoint)Listener.LocalEndPoint).Port Host Port [-r host:port] String loggingPath = "-L " + "\"" + KwmPath.GetKtlstunnelLogFilePath() + "ktlstunnel-" + KwmPath.GetLogFileName() + "\" "; String loggingLevel = ""; if (KwmCfg.Cur.KtlstunnelLoggingLevel == 1) { loggingLevel = "-l minimal "; loggingLevel += loggingPath; } else if (KwmCfg.Cur.KtlstunnelLoggingLevel == 2) { loggingLevel = "-l debug "; loggingLevel += loggingPath; } String startupLine = "\"" + KwmPath.KwmKtlstunnelPath + "\" " + loggingLevel + "localhost " + ((IPEndPoint)Sock.LocalEndPoint).Port.ToString() + " " + Host + " " + Port + " " + extraParams; KLogging.Log("Starting ktlstunnel.exe : " + startupLine); TunnelProcess = new KProcess(startupLine); TunnelProcess.InheritHandles = false; TunnelProcess.CreationFlags = (uint)KSyscalls.CREATION_FLAGS.CREATE_NO_WINDOW; TunnelProcess.Start(); }