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