|  |  | 
 |  |  |             FileSystem = FileSystem.Create();
 | 
 |  |  |         }
 | 
 |  |  | 
 | 
 |  |  |         Dictionary<Guid, Program> programs = new Dictionary<Guid, Program>();
 | 
 |  |  |         readonly Dictionary<Guid, Program> programs = new Dictionary<Guid, Program>();
 | 
 |  |  |         public IEnumerable<Program> Programs
 | 
 |  |  |         {
 | 
 |  |  |             get { return ThreadSafe(() => programs.Values.ToList()); }
 | 
 |  |  |         }
 | 
 |  |  | 
 | 
 |  |  |         HashSet<PendingBreakpoint> pendingBreakpoints = new HashSet<PendingBreakpoint>();
 | 
 |  |  |         readonly HashSet<PendingBreakpoint> pendingBreakpoints = new HashSet<PendingBreakpoint>();
 | 
 |  |  |         public IEnumerable<PendingBreakpoint> PendingBreakpoints
 | 
 |  |  |         {
 | 
 |  |  |             get { return ThreadSafe(() => pendingBreakpoints.ToList()); }
 | 
 |  |  | 
 |  |  |             if (string.IsNullOrEmpty(pszOptions))
 | 
 |  |  |                 return VSConstants.E_FAIL;
 | 
 |  |  | 
 | 
 |  |  |             uint procId;
 | 
 |  |  |             if (!uint.TryParse(pszOptions, out procId))
 | 
 |  |  |             if (!uint.TryParse(pszOptions, out uint procId))
 | 
 |  |  |                 return VSConstants.E_FAIL;
 | 
 |  |  | 
 | 
 |  |  |             var env = bstrEnv.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
 | 
 |  |  | 
 |  |  |                     FileSystem.RegisterRccFile(rccFile);
 | 
 |  |  |             }
 | 
 |  |  | 
 | 
 |  |  |             IDebugProcess2 nativeProc;
 | 
 |  |  |             var nativeProcId = new AD_PROCESS_ID
 | 
 |  |  |             {
 | 
 |  |  |                 ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM,
 | 
 |  |  |                 dwProcessId = procId
 | 
 |  |  |             };
 | 
 |  |  |             if (pPort.GetProcess(nativeProcId, out nativeProc) != VSConstants.S_OK)
 | 
 |  |  |             if (pPort.GetProcess(nativeProcId, out IDebugProcess2 nativeProc) != VSConstants.S_OK)
 | 
 |  |  |                 return VSConstants.E_FAIL;
 | 
 |  |  | 
 | 
 |  |  |             var program = Program.Create(this, nativeProc, pszExe, pszArgs);
 | 
 |  |  | 
 |  |  |             if (program == null)
 | 
 |  |  |                 return VSConstants.E_FAIL;
 | 
 |  |  | 
 | 
 |  |  |             IDebugPort2 port;
 | 
 |  |  |             if (process.GetPort(out port) != VSConstants.S_OK)
 | 
 |  |  |             if (process.GetPort(out IDebugPort2 port) != VSConstants.S_OK)
 | 
 |  |  |                 return VSConstants.E_FAIL;
 | 
 |  |  | 
 | 
 |  |  |             string portName;
 | 
 |  |  |             port.GetPortName(out portName);
 | 
 |  |  | 
 | 
 |  |  |             Guid guidPort;
 | 
 |  |  |             port.GetPortId(out guidPort);
 | 
 |  |  | 
 | 
 |  |  |             IDebugDefaultPort2 defaultPort = (IDebugDefaultPort2)port;
 | 
 |  |  | 
 | 
 |  |  |             IDebugPortNotify2 portNotify;
 | 
 |  |  |             if (defaultPort.GetPortNotify(out portNotify) != VSConstants.S_OK)
 | 
 |  |  |             if (defaultPort.GetPortNotify(out IDebugPortNotify2 portNotify) != VSConstants.S_OK)
 | 
 |  |  |                 return VSConstants.E_FAIL;
 | 
 |  |  | 
 | 
 |  |  |             if (portNotify.AddProgramNode(program) != VSConstants.S_OK)
 | 
 |  |  | 
 |  |  | 
 | 
 |  |  |             DebugEvent.Send(new EngineCreateEvent(this));
 | 
 |  |  | 
 | 
 |  |  |             Guid pguidProgramId;
 | 
 |  |  |             if (rgpPrograms[0].GetProgramId(out pguidProgramId) != VSConstants.S_OK)
 | 
 |  |  |             if (rgpPrograms[0].GetProgramId(out Guid pguidProgramId) != VSConstants.S_OK)
 | 
 |  |  |                 return VSConstants.E_FAIL;
 | 
 |  |  | 
 | 
 |  |  |             program.ProgramId = pguidProgramId;
 | 
 |  |  | 
 |  |  | 
 | 
 |  |  |         int IDebugEngineLaunch2.CanTerminateProcess(IDebugProcess2 pProcess)
 | 
 |  |  |         {
 | 
 |  |  |             Guid procId;
 | 
 |  |  |             if (pProcess.GetProcessId(out procId) != VSConstants.S_OK)
 | 
 |  |  |             if (pProcess.GetProcessId(out Guid procId) != VSConstants.S_OK)
 | 
 |  |  |                 return VSConstants.E_FAIL;
 | 
 |  |  | 
 | 
 |  |  |             Program program;
 | 
 |  |  |             if (!programs.TryGetValue(procId, out program))
 | 
 |  |  |                 return VSConstants.S_FALSE;
 | 
 |  |  | 
 | 
 |  |  |             return VSConstants.S_OK;
 | 
 |  |  |             return programs.TryGetValue(procId, out _) ? VSConstants.S_OK : VSConstants.S_FALSE;
 | 
 |  |  |         }
 | 
 |  |  | 
 | 
 |  |  |         public bool ProgramIsRunning(Program program)
 | 
 |  |  | 
 |  |  | 
 | 
 |  |  |         int IDebugEngineLaunch2.TerminateProcess(IDebugProcess2 pProcess)
 | 
 |  |  |         {
 | 
 |  |  |             Guid procId;
 | 
 |  |  |             if (pProcess.GetProcessId(out procId) != VSConstants.S_OK)
 | 
 |  |  |             if (pProcess.GetProcessId(out Guid procId) != VSConstants.S_OK)
 | 
 |  |  |                 return VSConstants.E_FAIL;
 | 
 |  |  | 
 | 
 |  |  |             Program program;
 | 
 |  |  |             if (!programs.TryGetValue(procId, out program))
 | 
 |  |  |             if (!programs.TryGetValue(procId, out Program program))
 | 
 |  |  |                 return VSConstants.S_FALSE;
 | 
 |  |  | 
 | 
 |  |  |             programs.Remove(procId);
 | 
 |  |  | 
 |  |  | 
 | 
 |  |  |         int IDebugEngine2.ContinueFromSynchronousEvent(IDebugEvent2 pEvent)
 | 
 |  |  |         {
 | 
 |  |  |             var evtProgramDestroy = pEvent as ProgramDestroyEvent;
 | 
 |  |  |             if (evtProgramDestroy != null)
 | 
 |  |  |             if (pEvent is ProgramDestroyEvent evtProgramDestroy)
 | 
 |  |  |                 evtProgramDestroy.Program.Dispose();
 | 
 |  |  | 
 | 
 |  |  |             return VSConstants.S_OK;
 | 
 |  |  | 
 |  |  | 
 | 
 |  |  |         #region //////////////////// Concurrent ///////////////////////////////////////////////////
 | 
 |  |  | 
 | 
 |  |  |         LocalConcurrent concurrent = new LocalConcurrent();
 | 
 |  |  |         readonly LocalConcurrent concurrent = new LocalConcurrent();
 | 
 |  |  |         class LocalConcurrent : Concurrent
 | 
 |  |  |         {
 | 
 |  |  |             public void LocalThreadSafe(Action action)
 |