1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
6 #include "dbgtransportsession.h"
7 #include "dbgtransportmanager.h"
8 #include "coreclrremotedebugginginterfaces.h"
12 #ifdef FEATURE_DBGIPC_TRANSPORT_DI
14 DbgTransportTarget *g_pDbgTransportTarget = NULL;
16 DbgTransportTarget::DbgTransportTarget()
18 memset(this, 0, sizeof(*this));
21 // Initialization routine called only by the DbgTransportManager.
22 HRESULT DbgTransportTarget::Init()
24 m_sLock.Init("DbgTransportTarget Lock", RSLock::cLockFlat, RSLock::LL_DBG_TRANSPORT_TARGET_LOCK);
29 // Shutdown routine called only by the DbgTransportManager.
30 void DbgTransportTarget::Shutdown()
32 DbgTransportLog(LC_Always, "DbgTransportTarget shutting down");
35 RSLockHolder lock(&m_sLock);
36 while (m_pProcessList)
38 ProcessEntry *pDelProcess = m_pProcessList;
39 m_pProcessList = m_pProcessList->m_pNext;
47 // Given a PID attempt to find or create a DbgTransportSession instance to manage a connection to a runtime in
48 // that process. Returns E_UNEXPECTED if the process can't be found. Also returns a handle that can be waited
49 // on for process termination.
50 HRESULT DbgTransportTarget::GetTransportForProcess(DWORD dwPID,
51 DbgTransportSession **ppTransport,
52 HANDLE *phProcessHandle)
54 RSLockHolder lock(&m_sLock);
57 ProcessEntry *entry = LocateProcessByPID(dwPID);
62 NewHolder<ProcessEntry> newEntry = new(nothrow) ProcessEntry();
66 NewHolder<DbgTransportSession> transport = new(nothrow) DbgTransportSession();
67 if (transport == NULL)
73 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);
76 transport->Shutdown();
77 return HRESULT_FROM_GetLastError();
80 // Initialize it (this immediately starts the remote connection process).
81 hr = transport->Init(dwPID, hProcess);
84 transport->Shutdown();
85 CloseHandle(hProcess);
90 newEntry.SuppressRelease();
91 entry->m_dwPID = dwPID;
92 entry->m_hProcess = hProcess;
93 entry->m_transport = transport;
94 transport.SuppressRelease();
95 entry->m_cProcessRef = 0;
97 // Adding new entry to the list.
98 entry->m_pNext = m_pProcessList;
99 m_pProcessList = entry;
102 entry->m_cProcessRef++;
103 _ASSERTE(entry->m_cProcessRef > 0);
104 _ASSERTE(entry->m_transport != NULL);
105 _ASSERTE((intptr_t)entry->m_hProcess > 0);
107 *ppTransport = entry->m_transport;
108 if (!DuplicateHandle(GetCurrentProcess(),
112 0, // ignored since we are going to pass DUPLICATE_SAME_ACCESS
114 DUPLICATE_SAME_ACCESS))
116 return HRESULT_FROM_GetLastError();
123 // Release another reference to the transport associated with dwPID. Once all references are gone (modulo the
124 // manager's own weak reference) clean up the transport and deallocate it.
125 void DbgTransportTarget::ReleaseTransport(DbgTransportSession *pTransport)
127 RSLockHolder lock(&m_sLock);
129 ProcessEntry *entry = m_pProcessList;
131 // Pointer to the pointer that points to *entry.
132 // It either points to m_pProcessList or m_pNext of some entry.
133 // It is used to fix the linked list after deletion of an entry.
134 ProcessEntry **prevPtr = &m_pProcessList;
136 // Looking for ProcessEntry with a given transport
140 _ASSERTE(entry->m_cProcessRef > 0);
141 _ASSERTE(entry->m_transport != NULL);
142 _ASSERTE((intptr_t)entry->m_hProcess > 0);
144 if (entry->m_transport == pTransport)
146 // Mark that it has one less holder now
147 entry->m_cProcessRef--;
149 // If no more holders remove the entry from the list and free resources
150 if (entry->m_cProcessRef == 0)
152 *prevPtr = entry->m_pNext;
157 prevPtr = &entry->m_pNext;
158 entry = entry->m_pNext;
161 _ASSERTE(!"Trying to release transport that doesn't belong to this DbgTransportTarget");
162 pTransport->Shutdown();
165 HRESULT DbgTransportTarget::CreateProcess(LPCWSTR lpApplicationName,
166 LPCWSTR lpCommandLine,
167 LPSECURITY_ATTRIBUTES lpProcessAttributes,
168 LPSECURITY_ATTRIBUTES lpThreadAttributes,
169 BOOL bInheritHandles,
170 DWORD dwCreationFlags,
171 LPVOID lpEnvironment,
172 LPCWSTR lpCurrentDirectory,
173 LPSTARTUPINFOW lpStartupInfo,
174 LPPROCESS_INFORMATION lpProcessInformation)
177 BOOL result = WszCreateProcess(lpApplicationName,
186 lpProcessInformation);
190 return HRESULT_FROM_GetLastError();
196 // Kill the process identified by PID.
197 void DbgTransportTarget::KillProcess(DWORD dwPID)
199 HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwPID);
200 if (hProcess != NULL)
202 TerminateProcess(hProcess, 0);
203 CloseHandle(hProcess);
207 DbgTransportTarget::ProcessEntry::~ProcessEntry()
209 CloseHandle(m_hProcess);
212 m_transport->Shutdown();
216 // Locate a process entry by PID. Assumes the lock is already held.
217 DbgTransportTarget::ProcessEntry *DbgTransportTarget::LocateProcessByPID(DWORD dwPID)
219 _ASSERTE(m_sLock.HasLock());
221 ProcessEntry *pProcess = m_pProcessList;
224 if (pProcess->m_dwPID == dwPID)
226 pProcess = pProcess->m_pNext;
231 #endif // FEATURE_DBGIPC_TRANSPORT_DI