/// <summary> /// Called when the invite to workspace command reply is received. /// </summary> private void HandleKasInviteResult(KasQuery query) { if (!CheckCtx(KwmCoreKwsOpStep.KasInvite)) return; if (m_ih.HandleKasInviteResult(query)) CompleteOp(); }
private void HandleAcceptChatReply(KasQuery ctx) { UInt32 type = ctx.Res.Type; if (type == KAnpType.KANP_RES_OK) { UInt32 userID = ctx.Cmd.Elements[3].UInt32; Logging.Log("Chat with " + m_helper.GetUserByID(userID).UiSimpleName + " accepted."); m_helper.ActivateKws(); m_helper.SelectUser(userID); } else Logging.Log(2, Misc.HandleUnexpectedKAnpReply("accept public chat", ctx.Res).Message); }
private void HandleDisconnectKwsReply(KasQuery ctx) { // We're now logged out. Ignore failures from the server, // this can happen legitimately if we send a logout command // before we get the result of the login command. m_kws.Sm.HandleNormalLogout(); }
/// <summary> /// Called when the invite to workspace command reply is received. /// Return true if the invitation was successful. /// </summary> public bool HandleKasInviteResult(KasQuery query) { try { AnpMsg res = query.Res; // Handle failures. if (res.Type != KAnpType.KANP_RES_KWS_INVITE_KWS) throw Misc.HandleUnexpectedKAnpReply("invite to " + Base.GetKwsString(), res); // Update the invitation information. InviteParams.WLEU = res.Elements[0].String; if (res.Elements[1].UInt32 != (UInt32)InviteParams.UserArray.Count) throw new Exception("invalid number of users invited"); int i = 2; foreach (KwsInviteOpUser u in InviteParams.UserArray) { u.EmailID = res.Elements[i++].String; u.Url = res.Elements[i++].String; u.Error = res.Elements[i++].String; } return true; } catch (Exception ex) { Op.HandleMiscFailure(ex); return false; } }
public void OnChatMsgReply(KasQuery ctx) { AnpMsg cmd = ctx.Cmd; AnpMsg res = ctx.Res; if (res.Type == KAnpType.KANP_RES_OK) DoOnSentChatMsgOK(new OnSentChatMsgOKEventArgs(cmd.Elements[1].UInt32, cmd.Elements[2].String)); else if (res.Type == KAnpType.KANP_RES_FAIL) DoOnSentChatMsgFailed(new OnSentChatMsgFailedEventArgs(cmd.Elements[1].UInt32, cmd.Elements[2].String, res.Elements[1].String)); else Logging.Log(2, "unexpected chat command reply"); }
/// <summary> /// Called when the login reply is received. /// </summary> private void HandleConnectKwsReply(KasQuery query) { Logging.Log("Got login reply, kws " + m_kws.InternalID + ", status " + m_kws.MainStatus); Debug.Assert(m_kws.LoginStatus == KwsLoginStatus.LoggingIn); // This is the standard login reply. if (query.Res.Type == KAnpType.KANP_RES_KWS_CONNECT_KWS) { // Get the provided information. KwsConnectRes r = new KwsConnectRes(query.Res); Logging.Log(m_currentStep + " login step: " + r.ErrMsg); // Dispatch. if (r.Code == KAnpType.KANP_KWS_LOGIN_OK) HandleConnectKwsSuccess(r); else if (r.Code == KAnpType.KANP_KWS_LOGIN_BAD_PWD_OR_TICKET) HandleBadPwdOrTicket(r); else HandleLoginFailure(TranslateKcdLoginStatusCode(r.Code), r.ErrMsg); } // This is an unexpected reply. else { HandleLoginFailure(KwsLoginResult.MiscKcdError, Misc.HandleUnexpectedKAnpReply("login", query.Res).Message); } }
/// <summary> /// Called when the invite to workspace command reply is received. /// </summary> private void HandleKasInviteResult(KasQuery query) { Logging.Log(1, "HandleKasInviteResult()"); if (!CheckCtx(KwmCoreKwsOpStep.KasInvite)) return; if (m_ih.HandleKasInviteResult(query)) CompleteSpawn(); }
private void HandleSetUserPwdResponse(KasQuery ctx) { if (!CheckCtx(KwmCoreKwsOpStep.SetUserPwd)) return; Debug.Assert(m_query == ctx); m_query = null; // FIXME if version >= 4 check against KANP_RES_KWS_PROP_CHANGE if (ctx.Res.Type == KAnpType.KANP_RES_OK) { m_kws.PostGuiExecRequest(new SetPwdGer(MessageBoxIcon.Information, "The new password has been set.")); // We have changed our own password. Save it. if (m_kws.CoreData.Credentials.UserID == m_targetUserId) { m_kws.CoreData.Credentials.Pwd = m_stringParam; m_kws.SetDirty(); } } else { try { String msg = "Unable to set the new password: " + ctx.Res.Elements[1].String; ReportFailureToUser(msg); } catch (Exception ex) { HandleMiscFailure(ex); return; } } CleanUpOnDone(); }
/// <summary> /// Called when the create workspace command reply is received. /// </summary> private void HandleCreateKwsOnKasResult(KasQuery query) { if (!CheckCtx(KwmCoreKwsOpStep.KasCreate)) return; try { AnpMsg res = query.Res; // Handle failures. if (res.Type != KAnpType.KANP_RES_MGT_KWS_CREATED) throw Misc.HandleUnexpectedKAnpReply("create " + Base.GetKwsString(), res); // Update the workspace credentials. Creds.ExternalID = res.Elements[0].UInt64; Creds.EmailID = res.Elements[1].String; // Perform the login. PerformKasLogin(); } catch (Exception ex) { HandleMiscFailure(ex); } }
/// <summary> /// Handle the result of the SKURL query. /// </summary private void HandleSkurlQueryResult(KasQuery query) { if (!CheckCtx(KwmCoreKwsOpStep.KasSkurl)) return; try { AnpMsg res = query.Res; AppKfs appKfs = (AppKfs)m_kws.AppTree[KAnpType.KANP_NS_KFS]; // Handle failures. if (res.Type != KAnpType.KANP_RES_KWS_UURL) throw Misc.HandleUnexpectedKAnpReply("get SKURL", res); // Get the SKURL. string skurl = res.Elements[0].String; // Get the date. DateTime attachDate = Base.KDateToDateTimeUTC(res.Elements[1].UInt64); if (m_attachFile.Count > 0) { string attachDest = GetAttachmentDirectory(attachDate); string workDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); string attachDir = Path.Combine(workDir, attachDest); string sourceDir = ""; List<string> externalFiles = new List<string>(); try { // Create the directory structure we are going to upload // on the KCD. Directory.CreateDirectory(attachDir); // This assumes that all files provided by Outlook will // come from the same directory, which is a more than reasonable // assumption considering that it's programmed to do just that. sourceDir = Path.GetDirectoryName(m_attachFile[0]); // Move the Outlook attachments inside that structure. foreach (string externalFile in m_attachFile) { string ef = Path.Combine(attachDir, Path.GetFileName(externalFile)); File.Move(externalFile, ef); } // Check if the directory where Outlook put its attachments is // empty and if so delete it. if (sourceDir != null) { if (Directory.GetFiles(sourceDir).Length == 0) Directory.Delete(sourceDir); } string[] dirs = Directory.GetDirectories(workDir, "*", SearchOption.TopDirectoryOnly); // The "Attachments" directory will already exists and it's no big deal // so make sure we don't get a prompt about it. GateConfirmActions confirmActions = new GateConfirmActions(); confirmActions.dirExistsAction = "o"; appKfs.Share.Gate.AddExternalFiles("", dirs, false, confirmActions); Logging.Log(2, "About to notify user of a file upload"); Wm.UiBroker.NotifyUser(new AttachManagementNotificationItem(m_kws, m_outlookRequest.Cmd)); } finally { // We can remove our work directory now. Directory.Delete(workDir, true); } } // Send the reply. AnpMsg rep = m_outlookRequest.MakeReply(OAnpType.OANP_RES_GET_SKURL); rep.AddString(skurl); m_outlookRequest.SendReply(rep); // We're done. CleanUpOnDone(true); } catch (Exception ex) { HandleMiscFailure(ex); } }
/// <summary> /// Handle the result of the SKURL query. /// </summary> private void HandleSkurlQueryResult(KasQuery query) { if (!CheckCtx(KwmCoreKwsOpStep.KasSkurl)) return; try { AnpMsg res = query.Res; AppKfs appKfs = (AppKfs)m_kws.AppTree[KAnpType.KANP_NS_KFS]; // Handle failures. if (res.Type != KAnpType.KANP_RES_KWS_UURL) throw Misc.HandleUnexpectedKAnpReply("get SKURL", res); // Get the SKURL. m_skurl = res.Elements[0].String; // Get the date. DateTime attachDate = Base.KDateToDateTimeUTC(res.Elements[1].UInt64); // Get the email ID. if (m_kws.Kas.MinorVersion >= 6) { m_emailID = res.Elements[2].UInt64; } else { m_emailID = 0; } // Handle file upload attachments. if (m_outlookAttachList.Count > 0) { // Set the share attachment directory path. m_shareAttachDirRelPath = m_kws.CoreData.Credentials.UserEmailAddress + "/" + attachDate.ToString("yyyy-MM-dd HH\\hmm\\mss") + " " + m_mailSubject + "/" + "Original attachments"; // Wait for the share to become idle. m_opStep = KwmCoreKwsOpStep.KfsIdle; KfsShare share = GetKfsShare(); if (share.IsKfsIdle()) OnKfsIdle(null, null); else share.OnKfsIdle += OnKfsIdle; } // We're done. else { HandleSuccess(); } } catch (Exception ex) { HandleMiscFailure(ex); } }
/// <summary> /// Handles when a Start Ticket is received. /// </summary> /// <param name="_context"></param> private void OnStartTicketResponse(KasQuery ctx) { Debug.Assert(m_state == AppSharingState.StartTicket); AnpMsg cmd = ctx.Cmd; AnpMsg res = ctx.Res; if (m_state != AppSharingState.StartTicket) { Logging.Log(2, "Received spurious Screen Sharing Start ticket."); return; } if (res.Type == KAnpType.KANP_RES_VNC_START_TICKET) { m_ticket = res.Elements[0].Bin; /* Start MetaVNC (specify the desired window's handle)*/ int handle = Int32.Parse((String)ctx.MetaData[0]); bool supportSession = (bool)ctx.MetaData[2]; String vncServerPath = "\"" + Base.GetKwmInstallationPath() + @"vnc\kappserver.exe" + "\""; String args = (handle == 0) ? " -shareall" : " -sharehwnd " + (String)ctx.MetaData[0]; // If a window is being shared (not the desktop), set // it visible and in foreground. if (handle != 0) { IntPtr hWnd = new IntPtr(handle); if (Syscalls.IsIconic(hWnd)) Syscalls.ShowWindowAsync(hWnd, (int)Syscalls.WindowStatus.SW_RESTORE); Base.KSetForegroundWindow(hWnd); } /* Remove any indication of previous server's listening port */ RegistryKey port = Base.GetKwmCURegKey(); port.DeleteValue(m_portRegItem, false); port.DeleteValue(m_portRegItemWritten, false); port.Close(); // Set registry options in order to allow/deny // remote control. SetSupportSessionMode(supportSession); Logging.Log("Starting the first instance of MetaVNC (no args)."); m_serverProcess = new RawProcess(vncServerPath); m_serverProcess.CreationFlags = (uint)Syscalls.CREATION_FLAGS.CREATE_NO_WINDOW; m_serverProcess.InheritHandles = false; Syscalls.STARTUPINFO si = new Syscalls.STARTUPINFO(); si.dwFlags = 1; m_serverProcess.StartupInfo = si; m_serverProcess.ProcessEnd += HandleOnProcessEnd; m_serverProcess.Start(); Logging.Log("Started."); /* Wait until we can get our hands on the process's window handle */ int retries = 15; bool found = false; while (retries > 0) { Logging.Log("Trying to start WinVNC ( " + retries + ")"); IntPtr serverHandle = Syscalls.FindWindow("WinVNC Tray Icon", 0); if (serverHandle != IntPtr.Zero) { found = true; break; } System.Threading.Thread.Sleep(250); retries--; } if (!found) throw new Exception("Screen sharing error: server could not be started."); /* Start another process of metaVNC. * This is needed to pass the window handle * we want, it was easier to do this that way * than to pass it directly on the cmd line when * starting the process the first time. */ Logging.Log("Starting MetaVNC for the second time (this is normal): " + vncServerPath + args); m_dummyServerProcess = new RawProcess(vncServerPath + args); m_dummyServerProcess.CreationFlags = (uint)Syscalls.CREATION_FLAGS.CREATE_NO_WINDOW; m_dummyServerProcess.InheritHandles = false; m_dummyServerProcess.StartupInfo = si; m_dummyServerProcess.ProcessEnd += HandleOnProcessEnd; m_dummyServerProcess.Start(); // Find out on which port we need to tell ktlstunnel to // connect to the server RegistryKey kwmKey = Base.GetKwmCURegKey(); object readPort = null; object portOK = null; // Actively poll the synchronization key for 6 seconds. retries = 30; found = false; while (retries > 0) { portOK = kwmKey.GetValue(m_portRegItemWritten); if (portOK != null) { found = true; break; } System.Threading.Thread.Sleep(200); retries--; } if (!found) { if (kwmKey != null) kwmKey.Close(); ResetToIdle(); Misc.KwmTellUser("Screen sharing error: a timeout occured while waiting for the server's listening port."); return; } // At this stage we can presume the port was // correctly really written by the VNC server. readPort = kwmKey.GetValue(m_portRegItem); kwmKey.Close(); if (port == null) { ResetToIdle(); Misc.KwmTellUser("Screen sharing error: unable to read the server's listening port."); return; } Logging.Log("Screen Sharing server's port: " + (int)readPort); /* Connect a new tunnel */ m_tunnel = Helper.CreateTunnel(); m_tunnel.Connect("localhost", (int)readPort); /* Negociate role */ AnpMsg inMsg = Helper.NewKAnpMsg(KAnpType.KANP_CMD_MGT_SELECT_ROLE); inMsg.AddUInt32(KAnpType.KANP_KCD_ROLE_APP_SHARE); m_tunnel.SendMsg(inMsg); AnpMsg outMsg = m_tunnel.GetMsg(); if (outMsg.Type == KAnpType.KANP_RES_FAIL) { ResetToIdle(); Misc.KwmTellUser(outMsg.Elements[1].String); return; } Debug.Assert(outMsg.Type == KAnpType.KANP_RES_OK); AnpMsg startSession = Helper.NewKAnpMsg(KAnpType.KANP_CMD_VNC_START_SESSION); startSession.AddBin(m_ticket); startSession.AddString((String)ctx.MetaData[1]); m_tunnel.SendMsg(startSession); outMsg = m_tunnel.GetMsg(); if (outMsg.Type == KAnpType.KANP_RES_FAIL) { ResetToIdle(); Misc.KwmTellUser(outMsg.Elements[1].String); return; } Debug.Assert(outMsg.Type == KAnpType.KANP_RES_VNC_START_SESSION); m_createdSessionID = outMsg.Elements[0].UInt64; /* Disconnect tunnel so it can connect to metaVNC server */ Logging.Log("About to call disconnect on ktlstunnel."); m_tunnel.Disconnect(); CurrentState = AppSharingState.Started; m_connectedSessionID = 0; StopInactivityMonitor(); // 10 minutes inactivityMonitor = MonitorCreator.CreateInstance(MonitorType.GlobalHookMonitor); inactivityMonitor.Interval = 600000; inactivityMonitor.Elapsed += new ElapsedEventHandler(HandleSessionTimeout); inactivityMonitor.Enabled = true; } else if (res.Type == KAnpType.KANP_RES_FAIL) { ResetToIdle(); Misc.KwmTellUser(res.Elements[1].String); } else { Logging.Log(2, "unexpected response in OnStartTicketResponse"); } }
private void OnConnectTicketResponse(KasQuery ctx) { Debug.Assert(m_state == AppSharingState.ConnectTicket); AnpMsg cmd = ctx.Cmd; AnpMsg res = ctx.Res; if (m_state != AppSharingState.ConnectTicket) { Logging.Log(2, "Received spurious Screen Sharing Connect ticket."); return; } if (res.Type == KAnpType.KANP_RES_VNC_CONNECT_TICKET) { m_ticket = res.Elements[0].Bin; // Remove any indication of previous client's listening port RegistryKey port = Base.GetKwmCURegKey(); port.DeleteValue(m_portRegItem, false); port.DeleteValue(m_portRegItemWritten, false); port.Close(); /* Start client. Force one parameter so that it does not * prompt for connection parameters */ String vncClientPath = "\"" + Base.GetKwmInstallationPath() + @"vnc\kappviewer.exe" + "\""; String args = " /shared /notoolbar /disableclipboard /encoding tight /compresslevel 9 localhost"; m_viewerProcess = new RawProcess(vncClientPath + args); m_viewerProcess.InheritHandles = false; m_viewerProcess.ProcessEnd += HandleOnProcessEnd; m_viewerProcess.Start(); RegistryKey kwmKey = Base.GetKwmCURegKey(); object _port = null; object _portOK = null; // Actively poll the synchronization // key for 6 secs int retries = 30; bool found = false; while (retries > 0) { _portOK = kwmKey.GetValue(m_portRegItemWritten); if (_portOK != null) { found = true; break; } System.Threading.Thread.Sleep(200); retries--; } if (!found) { if (kwmKey != null) kwmKey.Close(); ResetToIdle(); Misc.KwmTellUser("a timeout occured while waiting for the client's listening port."); return; } // At this stage we can presume the port was // correctly really written by the VNC server. _port = kwmKey.GetValue(m_portRegItem); kwmKey.Close(); if (_port == null) { ResetToIdle(); Misc.KwmTellUser("could not read client's listening port."); return; } Logging.Log("Read VNC client's port: " + (int)_port); /* Connect a new tunnel */ IAnpTunnel tunnel = Helper.CreateTunnel(); tunnel.Connect("localhost", (int)_port); /* Negociate role */ AnpMsg inMsg = Helper.NewKAnpMsg(KAnpType.KANP_CMD_MGT_SELECT_ROLE); inMsg.AddUInt32(KAnpType.KANP_KCD_ROLE_APP_SHARE); tunnel.SendMsg(inMsg); AnpMsg outMsg = tunnel.GetMsg(); if (outMsg.Type == KAnpType.KANP_RES_FAIL) { ResetToIdle(); Misc.KwmTellUser(outMsg.Elements[1].String); return; } Debug.Assert(outMsg.Type == KAnpType.KANP_RES_OK); AnpMsg startSession = Helper.NewKAnpMsg(KAnpType.KANP_CMD_VNC_CONNECT_SESSION); startSession.AddBin(m_ticket); tunnel.SendMsg(startSession); outMsg = tunnel.GetMsg(); if (outMsg.Type == KAnpType.KANP_RES_FAIL) { ResetToIdle(); Misc.KwmTellUser(outMsg.Elements[1].String); return; } Debug.Assert(outMsg.Type == KAnpType.KANP_RES_OK); Logging.Log("About to call disconnect"); tunnel.Disconnect(); CurrentState = AppSharingState.Connected; } else if (res.Type == KAnpType.KANP_RES_FAIL) { ResetToIdle(); Misc.KwmTellUser(res.Elements[1].String); } else { Logging.Log("unexpected response in OnConnectTicketResponse"); } }