xref: /reactos/dll/win32/mscoree/cordebug.c (revision 50cf16b3)
1 /*
2  *
3  * Copyright 2011 Alistair Leslie-Hughes
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 #include "mscoree_private.h"
21 
22 typedef struct DebugProcess
23 {
24     ICorDebugProcess ICorDebugProcess_iface;
25 
26     CorDebug *cordebug;
27 
28     DWORD dwProcessID;
29     HANDLE handle;
30     HANDLE thread;
31 
32     LONG ref;
33 } DebugProcess;
34 
35 static inline CorDebug *impl_from_ICorDebug( ICorDebug *iface )
36 {
37     return CONTAINING_RECORD(iface, CorDebug, ICorDebug_iface);
38 }
39 
40 static inline CorDebug *impl_from_ICorDebugProcessEnum( ICorDebugProcessEnum *iface )
41 {
42     return CONTAINING_RECORD(iface, CorDebug, ICorDebugProcessEnum_iface);
43 }
44 
45 static inline DebugProcess *impl_from_ICorDebugProcess( ICorDebugProcess *iface )
46 {
47     return CONTAINING_RECORD(iface, DebugProcess, ICorDebugProcess_iface);
48 }
49 
50 /* ICorDebugProcess Interface */
51 static HRESULT WINAPI cordebugprocess_QueryInterface(ICorDebugProcess *iface,
52                 REFIID riid, void **ppvObject)
53 {
54     DebugProcess *This = impl_from_ICorDebugProcess(iface);
55 
56     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
57 
58     if ( IsEqualGUID( riid, &IID_ICorDebugProcess ) ||
59          IsEqualGUID( riid, &IID_ICorDebugController ) ||
60          IsEqualGUID( riid, &IID_IUnknown ) )
61     {
62         *ppvObject = &This->ICorDebugProcess_iface;
63     }
64     else
65     {
66         FIXME("Unsupported interface %s\n", debugstr_guid(riid));
67         return E_NOINTERFACE;
68     }
69 
70     ICorDebugProcess_AddRef(iface);
71 
72     return S_OK;
73 }
74 
75 static ULONG WINAPI cordebugprocess_AddRef(ICorDebugProcess *iface)
76 {
77     DebugProcess *This = impl_from_ICorDebugProcess(iface);
78     ULONG ref = InterlockedIncrement(&This->ref);
79 
80     TRACE("%p ref=%u\n", This, ref);
81 
82     return ref;
83 }
84 
85 static ULONG WINAPI cordebugprocess_Release(ICorDebugProcess *iface)
86 {
87     DebugProcess *This = impl_from_ICorDebugProcess(iface);
88     ULONG ref = InterlockedDecrement(&This->ref);
89 
90     TRACE("%p ref=%u\n", This, ref);
91 
92     if (ref == 0)
93     {
94         if(This->handle)
95             CloseHandle(This->handle);
96 
97         if(This->thread)
98             CloseHandle(This->thread);
99 
100         if(This->cordebug)
101             ICorDebug_Release(&This->cordebug->ICorDebug_iface);
102 
103         HeapFree(GetProcessHeap(), 0, This);
104     }
105 
106     return ref;
107 }
108 
109 static HRESULT WINAPI cordebugprocess_Stop(ICorDebugProcess *iface, DWORD dwTimeoutIgnored)
110 {
111     DebugProcess *This = impl_from_ICorDebugProcess(iface);
112     FIXME("stub %p\n", This);
113     return E_NOTIMPL;
114 }
115 
116 static HRESULT WINAPI cordebugprocess_Continue(ICorDebugProcess *iface, BOOL fIsOutOfBand)
117 {
118     DebugProcess *This = impl_from_ICorDebugProcess(iface);
119     TRACE("%p\n", This);
120 
121     if(This->thread)
122         ResumeThread(This->thread);
123 
124     return S_OK;
125 }
126 
127 static HRESULT WINAPI cordebugprocess_IsRunning(ICorDebugProcess *iface, BOOL *pbRunning)
128 {
129     DebugProcess *This = impl_from_ICorDebugProcess(iface);
130     FIXME("stub %p\n", This);
131     return E_NOTIMPL;
132 }
133 
134 static HRESULT WINAPI cordebugprocess_HasQueuedCallbacks(ICorDebugProcess *iface,
135                 ICorDebugThread *pThread, BOOL *pbQueued)
136 {
137     DebugProcess *This = impl_from_ICorDebugProcess(iface);
138     FIXME("stub %p\n", This);
139     return E_NOTIMPL;
140 }
141 
142 static HRESULT WINAPI cordebugprocess_EnumerateThreads(ICorDebugProcess *iface,
143                 ICorDebugThreadEnum **ppThreads)
144 {
145     DebugProcess *This = impl_from_ICorDebugProcess(iface);
146     FIXME("stub %p\n", This);
147     return E_NOTIMPL;
148 }
149 
150 static HRESULT WINAPI cordebugprocess_SetAllThreadsDebugState(ICorDebugProcess *iface,
151                 CorDebugThreadState state, ICorDebugThread *pExceptThisThread)
152 {
153     DebugProcess *This = impl_from_ICorDebugProcess(iface);
154     FIXME("stub %p\n", This);
155     return E_NOTIMPL;
156 }
157 
158 static HRESULT WINAPI cordebugprocess_Detach(ICorDebugProcess *iface)
159 {
160     DebugProcess *This = impl_from_ICorDebugProcess(iface);
161     FIXME("stub %p\n", This);
162     return E_NOTIMPL;
163 }
164 
165 static HRESULT WINAPI cordebugprocess_Terminate(ICorDebugProcess *iface, UINT exitCode)
166 {
167     DebugProcess *This = impl_from_ICorDebugProcess(iface);
168     BOOL ret = TRUE;
169 
170     TRACE("%p\n", This);
171 
172     if(This->handle)
173     {
174         ret = TerminateProcess(This->handle, exitCode);
175         CloseHandle(This->handle);
176         This->handle = NULL;
177     }
178     return ret ? S_OK : E_FAIL;
179 }
180 
181 static HRESULT WINAPI cordebugprocess_CanCommitChanges(ICorDebugProcess *iface,
182                 ULONG cSnapshots, ICorDebugEditAndContinueSnapshot * pSnapshots[],
183                 ICorDebugErrorInfoEnum **pError)
184 {
185     DebugProcess *This = impl_from_ICorDebugProcess(iface);
186     FIXME("stub %p\n", This);
187     return E_NOTIMPL;
188 }
189 
190 static HRESULT WINAPI cordebugprocess_CommitChanges(ICorDebugProcess *iface,
191                 ULONG cSnapshots, ICorDebugEditAndContinueSnapshot * pSnapshots[],
192                 ICorDebugErrorInfoEnum **pError)
193 {
194     DebugProcess *This = impl_from_ICorDebugProcess(iface);
195     FIXME("stub %p\n", This);
196     return E_NOTIMPL;
197 }
198 
199 static HRESULT WINAPI cordebugprocess_GetID(ICorDebugProcess *iface, DWORD *pdwProcessId)
200 {
201     DebugProcess *This = impl_from_ICorDebugProcess(iface);
202     TRACE("%p\n", This);
203 
204     if(!pdwProcessId)
205         return E_INVALIDARG;
206 
207     *pdwProcessId = This->dwProcessID;
208 
209     return S_OK;
210 }
211 
212 static HRESULT WINAPI cordebugprocess_GetHandle(ICorDebugProcess *iface, HPROCESS *phProcessHandle)
213 {
214     DebugProcess *This = impl_from_ICorDebugProcess(iface);
215     TRACE("%p\n", This);
216 
217     if(!phProcessHandle)
218         return E_INVALIDARG;
219 
220     *phProcessHandle = This->handle;
221 
222     return S_OK;
223 }
224 
225 static HRESULT WINAPI cordebugprocess_GetThread(ICorDebugProcess *iface, DWORD dwThreadId,
226                 ICorDebugThread **ppThread)
227 {
228     DebugProcess *This = impl_from_ICorDebugProcess(iface);
229     FIXME("stub %p\n", This);
230     return E_NOTIMPL;
231 }
232 
233 static HRESULT WINAPI cordebugprocess_EnumerateObjects(ICorDebugProcess *iface,
234                 ICorDebugObjectEnum **ppObjects)
235 {
236     DebugProcess *This = impl_from_ICorDebugProcess(iface);
237     FIXME("stub %p\n", This);
238     return E_NOTIMPL;
239 }
240 
241 static HRESULT WINAPI cordebugprocess_IsTransitionStub(ICorDebugProcess *iface,
242                 CORDB_ADDRESS address, BOOL *pbTransitionStub)
243 {
244     DebugProcess *This = impl_from_ICorDebugProcess(iface);
245     FIXME("stub %p\n", This);
246     return E_NOTIMPL;
247 }
248 
249 static HRESULT WINAPI cordebugprocess_IsOSSuspended(ICorDebugProcess *iface,
250                 DWORD threadID, BOOL *pbSuspended)
251 {
252     DebugProcess *This = impl_from_ICorDebugProcess(iface);
253     FIXME("stub %p\n", This);
254     return E_NOTIMPL;
255 }
256 
257 static HRESULT WINAPI cordebugprocess_GetThreadContext(ICorDebugProcess *iface,
258                 DWORD threadID, ULONG32 contextSize, BYTE context[])
259 {
260     DebugProcess *This = impl_from_ICorDebugProcess(iface);
261     FIXME("stub %p\n", This);
262     return E_NOTIMPL;
263 }
264 
265 static HRESULT WINAPI cordebugprocess_SetThreadContext(ICorDebugProcess *iface,
266                 DWORD threadID, ULONG32 contextSize, BYTE context[])
267 {
268     DebugProcess *This = impl_from_ICorDebugProcess(iface);
269     FIXME("stub %p\n", This);
270     return E_NOTIMPL;
271 }
272 
273 static HRESULT WINAPI cordebugprocess_ReadMemory(ICorDebugProcess *iface,
274                 CORDB_ADDRESS address, DWORD size, BYTE buffer[],
275                 SIZE_T *read)
276 {
277     DebugProcess *This = impl_from_ICorDebugProcess(iface);
278     FIXME("stub %p\n", This);
279     return E_NOTIMPL;
280 }
281 
282 static HRESULT WINAPI cordebugprocess_WriteMemory(ICorDebugProcess *iface,
283                 CORDB_ADDRESS address, DWORD size, BYTE buffer[],
284                 SIZE_T *written)
285 {
286     DebugProcess *This = impl_from_ICorDebugProcess(iface);
287     FIXME("stub %p\n", This);
288     return E_NOTIMPL;
289 }
290 
291 static HRESULT WINAPI cordebugprocess_ClearCurrentException(ICorDebugProcess *iface,
292                 DWORD threadID)
293 {
294     DebugProcess *This = impl_from_ICorDebugProcess(iface);
295     FIXME("stub %p\n", This);
296     return E_NOTIMPL;
297 }
298 
299 static HRESULT WINAPI cordebugprocess_EnableLogMessages(ICorDebugProcess *iface,
300                 BOOL fOnOff)
301 {
302     DebugProcess *This = impl_from_ICorDebugProcess(iface);
303     FIXME("stub %p\n", This);
304     return E_NOTIMPL;
305 }
306 
307 static HRESULT WINAPI cordebugprocess_ModifyLogSwitch(ICorDebugProcess *iface,
308                 WCHAR *pLogSwitchName, LONG lLevel)
309 {
310     DebugProcess *This = impl_from_ICorDebugProcess(iface);
311     FIXME("stub %p\n", This);
312     return E_NOTIMPL;
313 }
314 
315 static HRESULT WINAPI cordebugprocess_EnumerateAppDomains(ICorDebugProcess *iface,
316                 ICorDebugAppDomainEnum **ppAppDomains)
317 {
318     DebugProcess *This = impl_from_ICorDebugProcess(iface);
319     FIXME("stub %p\n", This);
320     return E_NOTIMPL;
321 }
322 
323 static HRESULT WINAPI cordebugprocess_GetObject(ICorDebugProcess *iface,
324                 ICorDebugValue **ppObject)
325 {
326     DebugProcess *This = impl_from_ICorDebugProcess(iface);
327     FIXME("stub %p\n", This);
328     return E_NOTIMPL;
329 }
330 
331 static HRESULT WINAPI cordebugprocess_ThreadForFiberCookie(ICorDebugProcess *iface,
332                 DWORD fiberCookie, ICorDebugThread **ppThread)
333 {
334     DebugProcess *This = impl_from_ICorDebugProcess(iface);
335     FIXME("stub %p\n", This);
336     return E_NOTIMPL;
337 }
338 
339 static HRESULT WINAPI cordebugprocess_GetHelperThreadID(ICorDebugProcess *iface,
340                 DWORD *pThreadID)
341 {
342     DebugProcess *This = impl_from_ICorDebugProcess(iface);
343     FIXME("stub %p\n", This);
344     return E_NOTIMPL;
345 }
346 
347 
348 /***************************************/
349 static const ICorDebugProcessVtbl cordebugprocessVtbl = {
350     cordebugprocess_QueryInterface,
351     cordebugprocess_AddRef,
352     cordebugprocess_Release,
353     cordebugprocess_Stop,
354     cordebugprocess_Continue,
355     cordebugprocess_IsRunning,
356     cordebugprocess_HasQueuedCallbacks,
357     cordebugprocess_EnumerateThreads,
358     cordebugprocess_SetAllThreadsDebugState,
359     cordebugprocess_Detach,
360     cordebugprocess_Terminate,
361     cordebugprocess_CanCommitChanges,
362     cordebugprocess_CommitChanges,
363     cordebugprocess_GetID,
364     cordebugprocess_GetHandle,
365     cordebugprocess_GetThread,
366     cordebugprocess_EnumerateObjects,
367     cordebugprocess_IsTransitionStub,
368     cordebugprocess_IsOSSuspended,
369     cordebugprocess_GetThreadContext,
370     cordebugprocess_SetThreadContext,
371     cordebugprocess_ReadMemory,
372     cordebugprocess_WriteMemory,
373     cordebugprocess_ClearCurrentException,
374     cordebugprocess_EnableLogMessages,
375     cordebugprocess_ModifyLogSwitch,
376     cordebugprocess_EnumerateAppDomains,
377     cordebugprocess_GetObject,
378     cordebugprocess_ThreadForFiberCookie,
379     cordebugprocess_GetHelperThreadID
380 };
381 
382 
383 static HRESULT CorDebugProcess_Create(CorDebug *cordebug, IUnknown** ppUnk, LPPROCESS_INFORMATION lpProcessInformation)
384 {
385     DebugProcess *This;
386 
387     This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
388     if ( !This )
389         return E_OUTOFMEMORY;
390 
391     if(!DuplicateHandle(GetCurrentProcess(), lpProcessInformation->hProcess,
392                     GetCurrentProcess(), &This->handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
393     {
394         ERR("Failed to duplicate process handle\n");
395         HeapFree(GetProcessHeap(), 0, This);
396         return E_FAIL;
397     }
398     if(!DuplicateHandle(GetCurrentProcess(), lpProcessInformation->hThread,
399                     GetCurrentProcess(), &This->thread, 0, FALSE, DUPLICATE_SAME_ACCESS))
400     {
401         CloseHandle(This->handle);
402 
403         ERR("Failed to duplicate thread handle\n");
404         HeapFree(GetProcessHeap(), 0, This);
405         return E_FAIL;
406     }
407 
408     This->ICorDebugProcess_iface.lpVtbl = &cordebugprocessVtbl;
409     This->ref = 1;
410     This->cordebug = cordebug;
411     This->dwProcessID = lpProcessInformation->dwProcessId;
412 
413     if(This->cordebug)
414         ICorDebug_AddRef(&This->cordebug->ICorDebug_iface);
415 
416     *ppUnk = (IUnknown*)&This->ICorDebugProcess_iface;
417 
418     return S_OK;
419 }
420 
421 /* ICorDebugProcessEnum Interface */
422 static HRESULT WINAPI process_enum_QueryInterface(ICorDebugProcessEnum *iface, REFIID riid, void **ppvObject)
423 {
424     CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
425 
426     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
427 
428     if ( IsEqualGUID( riid, &IID_ICorDebugProcessEnum ) ||
429          IsEqualGUID( riid, &IID_ICorDebugEnum ) ||
430          IsEqualGUID( riid, &IID_IUnknown ) )
431     {
432         *ppvObject = &This->ICorDebugProcessEnum_iface;
433     }
434     else
435     {
436         FIXME("Unsupported interface %s\n", debugstr_guid(riid));
437         return E_NOINTERFACE;
438     }
439 
440     ICorDebugProcessEnum_AddRef(iface);
441 
442     return S_OK;
443 }
444 
445 static ULONG WINAPI process_enum_AddRef(ICorDebugProcessEnum *iface)
446 {
447     CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
448     TRACE("%p ref=%u\n", This, This->ref);
449 
450     return ICorDebug_AddRef(&This->ICorDebug_iface);
451 }
452 
453 static ULONG WINAPI process_enum_Release(ICorDebugProcessEnum *iface)
454 {
455     CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
456     TRACE("%p ref=%u\n", This, This->ref);
457 
458     return ICorDebug_Release(&This->ICorDebug_iface);
459 }
460 
461 static HRESULT WINAPI process_enum_Skip(ICorDebugProcessEnum *iface, ULONG celt)
462 {
463     CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
464     FIXME("stub %p\n", This);
465     return E_NOTIMPL;
466 }
467 
468 static HRESULT WINAPI process_enum_Reset(ICorDebugProcessEnum *iface)
469 {
470     CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
471     FIXME("stub %p\n", This);
472     return E_NOTIMPL;
473 }
474 
475 static HRESULT WINAPI process_enum_Clone(ICorDebugProcessEnum *iface, ICorDebugEnum **ppEnum)
476 {
477     CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
478     FIXME("stub %p %p\n", This, ppEnum);
479     return E_NOTIMPL;
480 }
481 
482 static HRESULT WINAPI process_enum_GetCount(ICorDebugProcessEnum *iface, ULONG *pcelt)
483 {
484     CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
485     TRACE("stub %p %p\n", This, pcelt);
486 
487     if(!pcelt)
488         return E_INVALIDARG;
489 
490     *pcelt = list_count(&This->processes);
491 
492     return S_OK;
493 }
494 
495 static HRESULT WINAPI process_enum_Next(ICorDebugProcessEnum *iface, ULONG celt,
496             ICorDebugProcess * processes[], ULONG *pceltFetched)
497 {
498     CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
499     FIXME("stub %p %d %p %p\n", This, celt, processes, pceltFetched);
500     return E_NOTIMPL;
501 }
502 
503 static const struct ICorDebugProcessEnumVtbl processenum_vtbl =
504 {
505     process_enum_QueryInterface,
506     process_enum_AddRef,
507     process_enum_Release,
508     process_enum_Skip,
509     process_enum_Reset,
510     process_enum_Clone,
511     process_enum_GetCount,
512     process_enum_Next
513 };
514 
515 /*** IUnknown methods ***/
516 static HRESULT WINAPI CorDebug_QueryInterface(ICorDebug *iface, REFIID riid, void **ppvObject)
517 {
518     CorDebug *This = impl_from_ICorDebug( iface );
519 
520     TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
521 
522     if ( IsEqualGUID( riid, &IID_ICorDebug ) ||
523          IsEqualGUID( riid, &IID_IUnknown ) )
524     {
525         *ppvObject = &This->ICorDebug_iface;
526     }
527     else
528     {
529         FIXME("Unsupported interface %s\n", debugstr_guid(riid));
530         return E_NOINTERFACE;
531     }
532 
533     ICorDebug_AddRef( iface );
534 
535     return S_OK;
536 }
537 
538 static ULONG WINAPI CorDebug_AddRef(ICorDebug *iface)
539 {
540     CorDebug *This = impl_from_ICorDebug( iface );
541     ULONG ref = InterlockedIncrement(&This->ref);
542 
543     TRACE("%p ref=%u\n", This, ref);
544 
545     return ref;
546 }
547 
548 static ULONG WINAPI CorDebug_Release(ICorDebug *iface)
549 {
550     CorDebug *This = impl_from_ICorDebug( iface );
551     ULONG ref = InterlockedDecrement(&This->ref);
552 
553     TRACE("%p ref=%u\n", This, ref);
554 
555     if (ref == 0)
556     {
557         if(!list_empty(&This->processes))
558             ERR("Processes haven't been removed Correctly\n");
559 
560         if(This->runtimehost)
561             ICLRRuntimeHost_Release(This->runtimehost);
562 
563         if(This->pCallback)
564             ICorDebugManagedCallback2_Release(This->pCallback2);
565 
566         if(This->pCallback)
567             ICorDebugManagedCallback_Release(This->pCallback);
568 
569         HeapFree(GetProcessHeap(), 0, This);
570     }
571 
572     return ref;
573 }
574 
575 /*** ICorDebug methods ***/
576 static HRESULT WINAPI CorDebug_Initialize(ICorDebug *iface)
577 {
578     CorDebug *This = impl_from_ICorDebug( iface );
579     FIXME("stub %p\n", This);
580     return S_OK;
581 }
582 
583 static HRESULT WINAPI CorDebug_Terminate(ICorDebug *iface)
584 {
585     struct CorProcess *cursor, *cursor2;
586     CorDebug *This = impl_from_ICorDebug( iface );
587     TRACE("stub %p\n", This);
588 
589     LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->processes, struct CorProcess, entry)
590     {
591         if(cursor->pProcess)
592         {
593             ICorDebugProcess_Terminate(cursor->pProcess, 0);
594             ICorDebugProcess_Release(cursor->pProcess);
595         }
596 
597         list_remove(&cursor->entry);
598         HeapFree(GetProcessHeap(), 0, cursor);
599     }
600 
601     return S_OK;
602 }
603 
604 static HRESULT WINAPI CorDebug_SetManagedHandler(ICorDebug *iface, ICorDebugManagedCallback *pCallback)
605 {
606     CorDebug *This = impl_from_ICorDebug( iface );
607     HRESULT hr;
608     ICorDebugManagedCallback2 *pCallback2;
609 
610     TRACE("%p (%p)\n", This, pCallback);
611 
612     if(!pCallback)
613         return E_INVALIDARG;
614 
615     hr = ICorDebugManagedCallback_QueryInterface(pCallback, &IID_ICorDebugManagedCallback2, (void**)&pCallback2);
616     if(hr == S_OK)
617     {
618         if(This->pCallback2)
619             ICorDebugManagedCallback2_Release(This->pCallback2);
620 
621         if(This->pCallback)
622             ICorDebugManagedCallback_Release(This->pCallback);
623 
624         This->pCallback = pCallback;
625         This->pCallback2 = pCallback2;
626 
627         ICorDebugManagedCallback_AddRef(This->pCallback);
628     }
629     else
630     {
631         WARN("Debugging without interface ICorDebugManagedCallback2 is currently not supported.\n");
632     }
633 
634     return hr;
635 }
636 
637 static HRESULT WINAPI CorDebug_SetUnmanagedHandler(ICorDebug *iface, ICorDebugUnmanagedCallback *pCallback)
638 {
639     CorDebug *This = impl_from_ICorDebug( iface );
640     FIXME("stub %p %p\n", This, pCallback);
641     return E_NOTIMPL;
642 }
643 
644 static HRESULT WINAPI CorDebug_CreateProcess(ICorDebug *iface, LPCWSTR lpApplicationName,
645             LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
646             LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
647             DWORD dwCreationFlags, PVOID lpEnvironment,LPCWSTR lpCurrentDirectory,
648             LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation,
649             CorDebugCreateProcessFlags debuggingFlags, ICorDebugProcess **ppProcess)
650 {
651     CorDebug *This = impl_from_ICorDebug( iface );
652     ICorDebugProcess *pDebugProcess;
653     HRESULT hr;
654 
655     TRACE("stub %p %s %s %p %p %d %d %p %s %p %p %d %p\n", This, debugstr_w(lpApplicationName),
656             debugstr_w(lpCommandLine), lpProcessAttributes, lpThreadAttributes,
657             bInheritHandles, dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
658             lpStartupInfo, lpProcessInformation, debuggingFlags, ppProcess);
659 
660     if(CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes,
661             bInheritHandles, dwCreationFlags | CREATE_SUSPENDED, lpEnvironment, lpCurrentDirectory,
662             lpStartupInfo, lpProcessInformation))
663     {
664         hr = CorDebugProcess_Create(This, (IUnknown**)&pDebugProcess, lpProcessInformation);
665         if(hr == S_OK)
666         {
667             struct CorProcess *new_process = HeapAlloc( GetProcessHeap(), 0, sizeof(CorProcess) );
668 
669             new_process->pProcess = pDebugProcess;
670             list_add_tail(&This->processes, &new_process->entry);
671 
672             ICorDebugProcess_AddRef(pDebugProcess);
673             *ppProcess = pDebugProcess;
674 
675             if(This->pCallback)
676                 ICorDebugManagedCallback_CreateProcess(This->pCallback, pDebugProcess);
677         }
678         else
679         {
680             TerminateProcess(lpProcessInformation->hProcess, 0);
681         }
682     }
683     else
684         hr = E_FAIL;
685 
686     return hr;
687 }
688 
689 static HRESULT WINAPI CorDebug_DebugActiveProcess(ICorDebug *iface, DWORD id, BOOL win32Attach,
690             ICorDebugProcess **ppProcess)
691 {
692     CorDebug *This = impl_from_ICorDebug( iface );
693     FIXME("stub %p %d %d %p\n", This, id, win32Attach, ppProcess);
694     return E_NOTIMPL;
695 }
696 
697 static HRESULT WINAPI CorDebug_EnumerateProcesses( ICorDebug *iface, ICorDebugProcessEnum **ppProcess)
698 {
699     CorDebug *This = impl_from_ICorDebug( iface );
700     TRACE("stub %p %p\n", This, ppProcess);
701 
702     if(!ppProcess)
703         return E_INVALIDARG;
704 
705     *ppProcess = &This->ICorDebugProcessEnum_iface;
706     ICorDebugProcessEnum_AddRef(*ppProcess);
707 
708     return S_OK;
709 }
710 
711 static HRESULT WINAPI CorDebug_GetProcess(ICorDebug *iface, DWORD dwProcessId, ICorDebugProcess **ppProcess)
712 {
713     CorDebug *This = impl_from_ICorDebug( iface );
714     FIXME("stub %p %d %p\n", This, dwProcessId, ppProcess);
715     return E_NOTIMPL;
716 }
717 
718 static HRESULT WINAPI CorDebug_CanLaunchOrAttach(ICorDebug *iface, DWORD dwProcessId,
719             BOOL win32DebuggingEnabled)
720 {
721     CorDebug *This = impl_from_ICorDebug( iface );
722     FIXME("stub %p %d %d\n", This, dwProcessId, win32DebuggingEnabled);
723     return S_OK;
724 }
725 
726 static const struct ICorDebugVtbl cordebug_vtbl =
727 {
728     CorDebug_QueryInterface,
729     CorDebug_AddRef,
730     CorDebug_Release,
731     CorDebug_Initialize,
732     CorDebug_Terminate,
733     CorDebug_SetManagedHandler,
734     CorDebug_SetUnmanagedHandler,
735     CorDebug_CreateProcess,
736     CorDebug_DebugActiveProcess,
737     CorDebug_EnumerateProcesses,
738     CorDebug_GetProcess,
739     CorDebug_CanLaunchOrAttach
740 };
741 
742 HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk)
743 {
744     CorDebug *This;
745 
746     This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
747     if ( !This )
748         return E_OUTOFMEMORY;
749 
750     This->ICorDebug_iface.lpVtbl = &cordebug_vtbl;
751     This->ICorDebugProcessEnum_iface.lpVtbl = &processenum_vtbl;
752     This->ref = 1;
753     This->pCallback = NULL;
754     This->pCallback2 = NULL;
755     This->runtimehost = runtimehost;
756 
757     list_init(&This->processes);
758 
759     if(This->runtimehost)
760         ICLRRuntimeHost_AddRef(This->runtimehost);
761 
762     *ppUnk = (IUnknown*)&This->ICorDebug_iface;
763 
764     return S_OK;
765 }
766