cabinet: Preserve trailing slash on directory name in Extract().
[wine/multimedia.git] / dlls / mscoree / corruntimehost.c
blob3c26340a82ae80cdda7889771c68434f68840bb6
1 /*
3 * Copyright 2008 Alistair Leslie-Hughes
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.
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.
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
20 #define COBJMACROS
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winnls.h"
28 #include "winreg.h"
29 #include "ole2.h"
30 #include "shellapi.h"
32 #include "cor.h"
33 #include "mscoree.h"
34 #include "metahost.h"
35 #include "wine/list.h"
36 #include "mscoree_private.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
42 struct RuntimeHost
44 const struct ICorRuntimeHostVtbl *lpVtbl;
45 const struct ICLRRuntimeHostVtbl *lpCLRHostVtbl;
46 const CLRRuntimeInfo *version;
47 const loaded_mono *mono;
48 struct list domains;
49 MonoDomain *default_domain;
50 CRITICAL_SECTION lock;
51 LONG ref;
54 struct DomainEntry
56 struct list entry;
57 MonoDomain *domain;
60 static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result)
62 struct DomainEntry *entry;
63 char *mscorlib_path;
64 HRESULT res=S_OK;
66 EnterCriticalSection(&This->lock);
68 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
69 if (!entry)
71 res = E_OUTOFMEMORY;
72 goto end;
75 mscorlib_path = WtoA(This->version->mscorlib_path);
76 if (!mscorlib_path)
78 HeapFree(GetProcessHeap(), 0, entry);
79 res = E_OUTOFMEMORY;
80 goto end;
83 entry->domain = This->mono->mono_jit_init(mscorlib_path);
85 HeapFree(GetProcessHeap(), 0, mscorlib_path);
87 if (!entry->domain)
89 HeapFree(GetProcessHeap(), 0, entry);
90 res = E_FAIL;
91 goto end;
94 list_add_tail(&This->domains, &entry->entry);
96 MSCOREE_LockModule();
98 *result = entry->domain;
100 end:
101 LeaveCriticalSection(&This->lock);
103 return res;
106 static HRESULT RuntimeHost_GetDefaultDomain(RuntimeHost *This, MonoDomain **result)
108 HRESULT res=S_OK;
110 EnterCriticalSection(&This->lock);
112 if (This->default_domain) goto end;
114 res = RuntimeHost_AddDomain(This, &This->default_domain);
116 end:
117 *result = This->default_domain;
119 LeaveCriticalSection(&This->lock);
121 return res;
124 static void RuntimeHost_DeleteDomain(RuntimeHost *This, MonoDomain *domain)
126 struct DomainEntry *entry;
128 EnterCriticalSection(&This->lock);
130 LIST_FOR_EACH_ENTRY(entry, &This->domains, struct DomainEntry, entry)
132 if (entry->domain == domain)
134 This->mono->mono_jit_cleanup(domain);
135 list_remove(&entry->entry);
136 if (This->default_domain == domain)
137 This->default_domain = NULL;
138 HeapFree(GetProcessHeap(), 0, entry);
139 MSCOREE_UnlockModule();
140 break;
144 LeaveCriticalSection(&This->lock);
147 static inline RuntimeHost *impl_from_ICLRRuntimeHost( ICLRRuntimeHost *iface )
149 return (RuntimeHost *)((char*)iface - FIELD_OFFSET(RuntimeHost, lpCLRHostVtbl));
152 static inline RuntimeHost *impl_from_ICorRuntimeHost( ICorRuntimeHost *iface )
154 return (RuntimeHost *)((char*)iface - FIELD_OFFSET(RuntimeHost, lpVtbl));
157 /*** IUnknown methods ***/
158 static HRESULT WINAPI corruntimehost_QueryInterface(ICorRuntimeHost* iface,
159 REFIID riid,
160 void **ppvObject)
162 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
163 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
165 if ( IsEqualGUID( riid, &IID_ICorRuntimeHost ) ||
166 IsEqualGUID( riid, &IID_IUnknown ) )
168 *ppvObject = iface;
170 else
172 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
173 return E_NOINTERFACE;
176 ICorRuntimeHost_AddRef( iface );
178 return S_OK;
181 static ULONG WINAPI corruntimehost_AddRef(ICorRuntimeHost* iface)
183 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
185 MSCOREE_LockModule();
187 return InterlockedIncrement( &This->ref );
190 static ULONG WINAPI corruntimehost_Release(ICorRuntimeHost* iface)
192 RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
193 ULONG ref;
195 MSCOREE_UnlockModule();
197 ref = InterlockedDecrement( &This->ref );
199 return ref;
202 /*** ICorRuntimeHost methods ***/
203 static HRESULT WINAPI corruntimehost_CreateLogicalThreadState(
204 ICorRuntimeHost* iface)
206 FIXME("stub %p\n", iface);
207 return E_NOTIMPL;
210 static HRESULT WINAPI corruntimehost_DeleteLogicalThreadState(
211 ICorRuntimeHost* iface)
213 FIXME("stub %p\n", iface);
214 return E_NOTIMPL;
217 static HRESULT WINAPI corruntimehost_SwitchInLogicalThreadState(
218 ICorRuntimeHost* iface,
219 DWORD *fiberCookie)
221 FIXME("stub %p\n", iface);
222 return E_NOTIMPL;
225 static HRESULT WINAPI corruntimehost_SwitchOutLogicalThreadState(
226 ICorRuntimeHost* iface,
227 DWORD **fiberCookie)
229 FIXME("stub %p\n", iface);
230 return E_NOTIMPL;
233 static HRESULT WINAPI corruntimehost_LocksHeldByLogicalThread(
234 ICorRuntimeHost* iface,
235 DWORD *pCount)
237 FIXME("stub %p\n", iface);
238 return E_NOTIMPL;
241 static HRESULT WINAPI corruntimehost_MapFile(
242 ICorRuntimeHost* iface,
243 HANDLE hFile,
244 HMODULE *mapAddress)
246 FIXME("stub %p\n", iface);
247 return E_NOTIMPL;
250 static HRESULT WINAPI corruntimehost_GetConfiguration(
251 ICorRuntimeHost* iface,
252 ICorConfiguration **pConfiguration)
254 FIXME("stub %p\n", iface);
255 return E_NOTIMPL;
258 static HRESULT WINAPI corruntimehost_Start(
259 ICorRuntimeHost* iface)
261 FIXME("stub %p\n", iface);
262 return E_NOTIMPL;
265 static HRESULT WINAPI corruntimehost_Stop(
266 ICorRuntimeHost* iface)
268 FIXME("stub %p\n", iface);
269 return E_NOTIMPL;
272 static HRESULT WINAPI corruntimehost_CreateDomain(
273 ICorRuntimeHost* iface,
274 LPCWSTR friendlyName,
275 IUnknown *identityArray,
276 IUnknown **appDomain)
278 FIXME("stub %p\n", iface);
279 return E_NOTIMPL;
282 static HRESULT WINAPI corruntimehost_GetDefaultDomain(
283 ICorRuntimeHost* iface,
284 IUnknown **pAppDomain)
286 FIXME("stub %p\n", iface);
287 return E_NOTIMPL;
290 static HRESULT WINAPI corruntimehost_EnumDomains(
291 ICorRuntimeHost* iface,
292 HDOMAINENUM *hEnum)
294 FIXME("stub %p\n", iface);
295 return E_NOTIMPL;
298 static HRESULT WINAPI corruntimehost_NextDomain(
299 ICorRuntimeHost* iface,
300 HDOMAINENUM hEnum,
301 IUnknown **appDomain)
303 FIXME("stub %p\n", iface);
304 return E_NOTIMPL;
307 static HRESULT WINAPI corruntimehost_CloseEnum(
308 ICorRuntimeHost* iface,
309 HDOMAINENUM hEnum)
311 FIXME("stub %p\n", iface);
312 return E_NOTIMPL;
315 static HRESULT WINAPI corruntimehost_CreateDomainEx(
316 ICorRuntimeHost* iface,
317 LPCWSTR friendlyName,
318 IUnknown *setup,
319 IUnknown *evidence,
320 IUnknown **appDomain)
322 FIXME("stub %p\n", iface);
323 return E_NOTIMPL;
326 static HRESULT WINAPI corruntimehost_CreateDomainSetup(
327 ICorRuntimeHost* iface,
328 IUnknown **appDomainSetup)
330 FIXME("stub %p\n", iface);
331 return E_NOTIMPL;
334 static HRESULT WINAPI corruntimehost_CreateEvidence(
335 ICorRuntimeHost* iface,
336 IUnknown **evidence)
338 FIXME("stub %p\n", iface);
339 return E_NOTIMPL;
342 static HRESULT WINAPI corruntimehost_UnloadDomain(
343 ICorRuntimeHost* iface,
344 IUnknown *appDomain)
346 FIXME("stub %p\n", iface);
347 return E_NOTIMPL;
350 static HRESULT WINAPI corruntimehost_CurrentDomain(
351 ICorRuntimeHost* iface,
352 IUnknown **appDomain)
354 FIXME("stub %p\n", iface);
355 return E_NOTIMPL;
358 static const struct ICorRuntimeHostVtbl corruntimehost_vtbl =
360 corruntimehost_QueryInterface,
361 corruntimehost_AddRef,
362 corruntimehost_Release,
363 corruntimehost_CreateLogicalThreadState,
364 corruntimehost_DeleteLogicalThreadState,
365 corruntimehost_SwitchInLogicalThreadState,
366 corruntimehost_SwitchOutLogicalThreadState,
367 corruntimehost_LocksHeldByLogicalThread,
368 corruntimehost_MapFile,
369 corruntimehost_GetConfiguration,
370 corruntimehost_Start,
371 corruntimehost_Stop,
372 corruntimehost_CreateDomain,
373 corruntimehost_GetDefaultDomain,
374 corruntimehost_EnumDomains,
375 corruntimehost_NextDomain,
376 corruntimehost_CloseEnum,
377 corruntimehost_CreateDomainEx,
378 corruntimehost_CreateDomainSetup,
379 corruntimehost_CreateEvidence,
380 corruntimehost_UnloadDomain,
381 corruntimehost_CurrentDomain
384 static HRESULT WINAPI CLRRuntimeHost_QueryInterface(ICLRRuntimeHost* iface,
385 REFIID riid,
386 void **ppvObject)
388 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
389 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
391 if ( IsEqualGUID( riid, &IID_ICLRRuntimeHost ) ||
392 IsEqualGUID( riid, &IID_IUnknown ) )
394 *ppvObject = iface;
396 else
398 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
399 return E_NOINTERFACE;
402 ICLRRuntimeHost_AddRef( iface );
404 return S_OK;
407 static ULONG WINAPI CLRRuntimeHost_AddRef(ICLRRuntimeHost* iface)
409 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
410 return IUnknown_AddRef((IUnknown*)&This->lpVtbl);
413 static ULONG WINAPI CLRRuntimeHost_Release(ICLRRuntimeHost* iface)
415 RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
416 return IUnknown_Release((IUnknown*)&This->lpVtbl);
419 static HRESULT WINAPI CLRRuntimeHost_Start(ICLRRuntimeHost* iface)
421 FIXME("(%p)\n", iface);
422 return E_NOTIMPL;
425 static HRESULT WINAPI CLRRuntimeHost_Stop(ICLRRuntimeHost* iface)
427 FIXME("(%p)\n", iface);
428 return E_NOTIMPL;
431 static HRESULT WINAPI CLRRuntimeHost_SetHostControl(ICLRRuntimeHost* iface,
432 IHostControl *pHostControl)
434 FIXME("(%p,%p)\n", iface, pHostControl);
435 return E_NOTIMPL;
438 static HRESULT WINAPI CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost* iface,
439 ICLRControl **pCLRControl)
441 FIXME("(%p,%p)\n", iface, pCLRControl);
442 return E_NOTIMPL;
445 static HRESULT WINAPI CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost* iface,
446 DWORD dwAppDomainId, BOOL fWaitUntilDone)
448 FIXME("(%p,%u,%i)\n", iface, dwAppDomainId, fWaitUntilDone);
449 return E_NOTIMPL;
452 static HRESULT WINAPI CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost* iface,
453 DWORD dwAppDomainId, FExecuteInAppDomainCallback pCallback, void *cookie)
455 FIXME("(%p,%u,%p,%p)\n", iface, dwAppDomainId, pCallback, cookie);
456 return E_NOTIMPL;
459 static HRESULT WINAPI CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost* iface,
460 DWORD *pdwAppDomainId)
462 FIXME("(%p,%p)\n", iface, pdwAppDomainId);
463 return E_NOTIMPL;
466 static HRESULT WINAPI CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost* iface,
467 LPCWSTR pwzAppFullName, DWORD dwManifestPaths, LPCWSTR *ppwzManifestPaths,
468 DWORD dwActivationData, LPCWSTR *ppwzActivationData, int *pReturnValue)
470 FIXME("(%p,%s,%u,%u)\n", iface, debugstr_w(pwzAppFullName), dwManifestPaths, dwActivationData);
471 return E_NOTIMPL;
474 static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost* iface,
475 LPCWSTR pwzAssemblyPath, LPCWSTR pwzTypeName, LPCWSTR pwzMethodName,
476 LPCWSTR pwzArgument, DWORD *pReturnValue)
478 FIXME("(%p,%s,%s,%s,%s)\n", iface, debugstr_w(pwzAssemblyPath),
479 debugstr_w(pwzTypeName), debugstr_w(pwzMethodName), debugstr_w(pwzArgument));
480 return E_NOTIMPL;
483 static const struct ICLRRuntimeHostVtbl CLRHostVtbl =
485 CLRRuntimeHost_QueryInterface,
486 CLRRuntimeHost_AddRef,
487 CLRRuntimeHost_Release,
488 CLRRuntimeHost_Start,
489 CLRRuntimeHost_Stop,
490 CLRRuntimeHost_SetHostControl,
491 CLRRuntimeHost_GetCLRControl,
492 CLRRuntimeHost_UnloadAppDomain,
493 CLRRuntimeHost_ExecuteInAppDomain,
494 CLRRuntimeHost_GetCurrentAppDomainId,
495 CLRRuntimeHost_ExecuteApplication,
496 CLRRuntimeHost_ExecuteInDefaultAppDomain
499 /* Create an instance of a type given its name, by calling its constructor with
500 * no arguments. Note that result MUST be in the stack, or the garbage
501 * collector may free it prematurely. */
502 HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
503 MonoDomain *domain, MonoObject **result)
505 HRESULT hr=S_OK;
506 char *nameA=NULL;
507 MonoType *type;
508 MonoClass *klass;
509 MonoObject *obj;
511 if (!domain)
512 hr = RuntimeHost_GetDefaultDomain(This, &domain);
514 if (SUCCEEDED(hr))
516 nameA = WtoA(name);
517 if (!nameA)
518 hr = E_OUTOFMEMORY;
521 if (SUCCEEDED(hr))
523 type = This->mono->mono_reflection_type_from_name(nameA, NULL);
524 if (!type)
526 ERR("Cannot find type %s\n", debugstr_w(name));
527 hr = E_FAIL;
531 if (SUCCEEDED(hr))
533 klass = This->mono->mono_class_from_mono_type(type);
534 if (!klass)
536 ERR("Cannot convert type %s to a class\n", debugstr_w(name));
537 hr = E_FAIL;
541 if (SUCCEEDED(hr))
543 obj = This->mono->mono_object_new(domain, klass);
544 if (!obj)
546 ERR("Cannot allocate object of type %s\n", debugstr_w(name));
547 hr = E_FAIL;
551 if (SUCCEEDED(hr))
553 /* FIXME: Detect exceptions from the constructor? */
554 This->mono->mono_runtime_object_init(obj);
555 *result = obj;
558 HeapFree(GetProcessHeap(), 0, nameA);
560 return hr;
563 /* Get an IUnknown pointer for a Mono object.
565 * This is just a "light" wrapper around
566 * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
568 * NOTE: The IUnknown* is created with a reference to the object.
569 * Until they have a reference, objects must be in the stack to prevent the
570 * garbage collector from freeing them. */
571 HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj,
572 IUnknown **ppUnk)
574 MonoDomain *domain;
575 MonoAssembly *assembly;
576 MonoImage *image;
577 MonoClass *klass;
578 MonoMethod *method;
579 MonoObject *result;
580 void *args[2];
582 domain = This->mono->mono_object_get_domain(obj);
584 assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
585 if (!assembly)
587 ERR("Cannot load mscorlib\n");
588 return E_FAIL;
591 image = This->mono->mono_assembly_get_image(assembly);
592 if (!image)
594 ERR("Couldn't get assembly image\n");
595 return E_FAIL;
598 klass = This->mono->mono_class_from_name(image, "System.Runtime.InteropServices", "Marshal");
599 if (!klass)
601 ERR("Couldn't get class from image\n");
602 return E_FAIL;
605 method = This->mono->mono_class_get_method_from_name(klass, "GetIUnknownForObject", 1);
606 if (!method)
608 ERR("Couldn't get method from class\n");
609 return E_FAIL;
612 args[0] = obj;
613 args[1] = NULL;
614 result = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
615 if (!result)
617 ERR("Couldn't get result pointer\n");
618 return E_FAIL;
621 *ppUnk = *(IUnknown**)This->mono->mono_object_unbox(result);
622 if (!*ppUnk)
624 ERR("GetIUnknownForObject returned 0\n");
625 return E_FAIL;
628 return S_OK;
631 static void get_utf8_args(int *argc, char ***argv)
633 WCHAR **argvw;
634 int size=0, i;
635 char *current_arg;
637 argvw = CommandLineToArgvW(GetCommandLineW(), argc);
639 for (i=0; i<*argc; i++)
641 size += sizeof(char*);
642 size += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
644 size += sizeof(char*);
646 *argv = HeapAlloc(GetProcessHeap(), 0, size);
647 current_arg = (char*)(*argv + *argc + 1);
649 for (i=0; i<*argc; i++)
651 (*argv)[i] = current_arg;
652 current_arg += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, current_arg, size, NULL, NULL);
655 (*argv)[*argc] = NULL;
657 HeapFree(GetProcessHeap(), 0, argvw);
660 __int32 WINAPI _CorExeMain(void)
662 int exit_code;
663 int argc;
664 char **argv;
665 MonoDomain *domain;
666 MonoAssembly *assembly;
667 WCHAR filename[MAX_PATH];
668 char *filenameA;
669 ICLRRuntimeInfo *info;
670 RuntimeHost *host;
671 HRESULT hr;
672 int i;
674 get_utf8_args(&argc, &argv);
676 GetModuleFileNameW(NULL, filename, MAX_PATH);
678 TRACE("%s", debugstr_w(filename));
679 for (i=0; i<argc; i++)
680 TRACE(" %s", debugstr_a(argv[i]));
681 TRACE("\n");
683 filenameA = WtoA(filename);
684 if (!filenameA)
685 return -1;
687 hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
689 if (SUCCEEDED(hr))
691 hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
693 if (SUCCEEDED(hr))
694 hr = RuntimeHost_GetDefaultDomain(host, &domain);
696 if (SUCCEEDED(hr))
698 assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
700 exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv);
702 RuntimeHost_DeleteDomain(host, domain);
704 else
705 exit_code = -1;
707 ICLRRuntimeInfo_Release(info);
709 else
710 exit_code = -1;
712 HeapFree(GetProcessHeap(), 0, argv);
714 return exit_code;
717 HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
718 const loaded_mono *loaded_mono, RuntimeHost** result)
720 RuntimeHost *This;
722 This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
723 if ( !This )
724 return E_OUTOFMEMORY;
726 This->lpVtbl = &corruntimehost_vtbl;
727 This->lpCLRHostVtbl = &CLRHostVtbl;
728 This->ref = 1;
729 This->version = runtime_version;
730 This->mono = loaded_mono;
731 list_init(&This->domains);
732 This->default_domain = NULL;
733 InitializeCriticalSection(&This->lock);
734 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RuntimeHost.lock");
736 *result = This;
738 return S_OK;
741 HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv)
743 IUnknown *unk;
744 HRESULT hr;
746 if (IsEqualGUID(clsid, &CLSID_CorRuntimeHost))
748 unk = (IUnknown*)&This->lpVtbl;
749 IUnknown_AddRef(unk);
751 else if (IsEqualGUID(clsid, &CLSID_CLRRuntimeHost))
753 unk = (IUnknown*)&This->lpCLRHostVtbl;
754 IUnknown_AddRef(unk);
756 else if (IsEqualGUID(clsid, &CLSID_CorMetaDataDispenser) ||
757 IsEqualGUID(clsid, &CLSID_CorMetaDataDispenserRuntime))
759 hr = MetaDataDispenser_CreateInstance(&unk);
760 if (FAILED(hr))
761 return hr;
763 else
764 unk = NULL;
766 if (unk)
768 hr = IUnknown_QueryInterface(unk, riid, ppv);
770 IUnknown_Release(unk);
772 return hr;
774 else
775 FIXME("not implemented for class %s\n", debugstr_guid(clsid));
777 return CLASS_E_CLASSNOTAVAILABLE;
780 HRESULT RuntimeHost_Destroy(RuntimeHost *This)
782 struct DomainEntry *cursor, *cursor2;
784 This->lock.DebugInfo->Spare[0] = 0;
785 DeleteCriticalSection(&This->lock);
787 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->domains, struct DomainEntry, entry)
789 This->mono->mono_jit_cleanup(cursor->domain);
790 list_remove(&cursor->entry);
791 HeapFree(GetProcessHeap(), 0, cursor);
794 HeapFree( GetProcessHeap(), 0, This );
795 return S_OK;