Пример #1
0
        private static void CreateProcess(
            string lpApplicationName,
            string lpCommandLine,
            bool bInheritHandles,
            uint dwCreationFlags,
            ref Syscalls.STARTUPINFO lpStartupInfo,
            out Syscalls.PROCESS_INFORMATION lpProcessInformation)
        {
            int retval;

            retval = Syscalls._CreateProcess(
                lpApplicationName,
                lpCommandLine,
                new IntPtr(0), new IntPtr(0),
                bInheritHandles,
                dwCreationFlags,
                new IntPtr(0), null,
                ref lpStartupInfo,
                out lpProcessInformation);

            if (retval == 0)
            {
                int errcode = Marshal.GetLastWin32Error();
                throw new Exception("Cannot create process (" + errcode + ": " + Syscalls.GetLastErrorStringMessage() + ")");
            }
        }
Пример #2
0
        /// <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");
            }
        }