2 * Copyright 2005 Juan Lang
3 * Copyright 2005-2006 Robert Shearman (for CodeWeavers)
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
22 #define WIN32_NO_STATUS
23 #define USE_COM_CONTEXT_DEF
30 #include "combase_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
38 static ULONG_PTR global_options
[COMGLB_PROPERTIES_RESERVED3
+ 1];
41 extern void WINAPI
DestroyRunningObjectTable(void);
42 extern HRESULT WINAPI
Ole32DllGetClassObject(REFCLSID rclsid
, REFIID riid
, void **obj
);
45 * Number of times CoInitialize is called. It is decreased every time CoUninitialize is called. When it hits 0, the COM libraries are freed
47 static LONG com_lockcount
;
49 static LONG com_server_process_refcount
;
51 struct comclassredirect_data
67 DWORD miscstatuscontent
;
68 DWORD miscstatusthumbnail
;
70 DWORD miscstatusdocprint
;
73 struct ifacepsredirect_data
85 struct progidredirect_data
106 static struct list registered_proxystubs
= LIST_INIT(registered_proxystubs
);
108 static CRITICAL_SECTION cs_registered_ps
;
109 static CRITICAL_SECTION_DEBUG psclsid_cs_debug
=
111 0, 0, &cs_registered_ps
,
112 { &psclsid_cs_debug
.ProcessLocksList
, &psclsid_cs_debug
.ProcessLocksList
},
113 0, 0, { (DWORD_PTR
)(__FILE__
": cs_registered_psclsid_list") }
115 static CRITICAL_SECTION cs_registered_ps
= { &psclsid_cs_debug
, -1, 0, 0, 0, 0 };
117 struct registered_class
126 unsigned int rpcss_cookie
;
129 static struct list registered_classes
= LIST_INIT(registered_classes
);
131 static CRITICAL_SECTION registered_classes_cs
;
132 static CRITICAL_SECTION_DEBUG registered_classes_cs_debug
=
134 0, 0, ®istered_classes_cs
,
135 { ®istered_classes_cs_debug
.ProcessLocksList
, ®istered_classes_cs_debug
.ProcessLocksList
},
136 0, 0, { (DWORD_PTR
)(__FILE__
": registered_classes_cs") }
138 static CRITICAL_SECTION registered_classes_cs
= { ®istered_classes_cs_debug
, -1, 0, 0, 0, 0 };
140 IUnknown
* com_get_registered_class_object(const struct apartment
*apt
, REFCLSID rclsid
, DWORD clscontext
)
142 struct registered_class
*cur
;
143 IUnknown
*object
= NULL
;
145 EnterCriticalSection(®istered_classes_cs
);
147 LIST_FOR_EACH_ENTRY(cur
, ®istered_classes
, struct registered_class
, entry
)
149 if ((apt
->oxid
== cur
->apartment_id
) &&
150 (clscontext
& cur
->clscontext
) &&
151 IsEqualGUID(&cur
->clsid
, rclsid
))
153 object
= cur
->object
;
154 IUnknown_AddRef(cur
->object
);
159 LeaveCriticalSection(®istered_classes_cs
);
164 static struct init_spy
*get_spy_entry(struct tlsdata
*tlsdata
, unsigned int id
)
166 struct init_spy
*spy
;
168 LIST_FOR_EACH_ENTRY(spy
, &tlsdata
->spies
, struct init_spy
, entry
)
170 if (id
== spy
->id
&& spy
->spy
)
177 static NTSTATUS
create_key(HKEY
*retkey
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
)
179 NTSTATUS status
= NtCreateKey((HANDLE
*)retkey
, access
, attr
, 0, NULL
, 0, NULL
);
181 if (status
== STATUS_OBJECT_NAME_NOT_FOUND
)
183 HANDLE subkey
, root
= attr
->RootDirectory
;
184 WCHAR
*buffer
= attr
->ObjectName
->Buffer
;
185 DWORD attrs
, pos
= 0, i
= 0, len
= attr
->ObjectName
->Length
/ sizeof(WCHAR
);
188 while (i
< len
&& buffer
[i
] != '\\') i
++;
189 if (i
== len
) return status
;
191 attrs
= attr
->Attributes
;
192 attr
->ObjectName
= &str
;
196 str
.Buffer
= buffer
+ pos
;
197 str
.Length
= (i
- pos
) * sizeof(WCHAR
);
198 status
= NtCreateKey(&subkey
, access
, attr
, 0, NULL
, 0, NULL
);
199 if (attr
->RootDirectory
!= root
) NtClose(attr
->RootDirectory
);
200 if (status
) return status
;
201 attr
->RootDirectory
= subkey
;
202 while (i
< len
&& buffer
[i
] == '\\') i
++;
204 while (i
< len
&& buffer
[i
] != '\\') i
++;
206 str
.Buffer
= buffer
+ pos
;
207 str
.Length
= (i
- pos
) * sizeof(WCHAR
);
208 attr
->Attributes
= attrs
;
209 status
= NtCreateKey((HANDLE
*)retkey
, access
, attr
, 0, NULL
, 0, NULL
);
210 if (attr
->RootDirectory
!= root
) NtClose(attr
->RootDirectory
);
215 static HKEY classes_root_hkey
;
217 static HKEY
create_classes_root_hkey(DWORD access
)
220 OBJECT_ATTRIBUTES attr
;
221 UNICODE_STRING name
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\Software\\Classes");
223 attr
.Length
= sizeof(attr
);
224 attr
.RootDirectory
= 0;
225 attr
.ObjectName
= &name
;
227 attr
.SecurityDescriptor
= NULL
;
228 attr
.SecurityQualityOfService
= NULL
;
230 if (create_key( &hkey
, access
, &attr
)) return 0;
231 TRACE( "%s -> %p\n", debugstr_w(attr
.ObjectName
->Buffer
), hkey
);
233 if (!(access
& KEY_WOW64_64KEY
))
235 if (!(ret
= InterlockedCompareExchangePointer( (void **)&classes_root_hkey
, hkey
, 0 )))
238 NtClose( hkey
); /* somebody beat us to it */
245 static HKEY
get_classes_root_hkey(HKEY hkey
, REGSAM access
);
247 static LSTATUS
create_classes_key(HKEY hkey
, const WCHAR
*name
, REGSAM access
, HKEY
*retkey
)
249 OBJECT_ATTRIBUTES attr
;
250 UNICODE_STRING nameW
;
252 if (!(hkey
= get_classes_root_hkey(hkey
, access
)))
253 return ERROR_INVALID_HANDLE
;
255 attr
.Length
= sizeof(attr
);
256 attr
.RootDirectory
= hkey
;
257 attr
.ObjectName
= &nameW
;
259 attr
.SecurityDescriptor
= NULL
;
260 attr
.SecurityQualityOfService
= NULL
;
261 RtlInitUnicodeString( &nameW
, name
);
263 return RtlNtStatusToDosError(create_key(retkey
, access
, &attr
));
266 static HKEY
get_classes_root_hkey(HKEY hkey
, REGSAM access
)
269 const BOOL is_win64
= sizeof(void*) > sizeof(int);
270 const BOOL force_wow32
= is_win64
&& (access
& KEY_WOW64_32KEY
);
272 if (hkey
== HKEY_CLASSES_ROOT
&&
273 ((access
& KEY_WOW64_64KEY
) || !(ret
= classes_root_hkey
)))
274 ret
= create_classes_root_hkey(MAXIMUM_ALLOWED
| (access
& KEY_WOW64_64KEY
));
275 if (force_wow32
&& ret
&& ret
== classes_root_hkey
)
277 access
&= ~KEY_WOW64_32KEY
;
278 if (create_classes_key(classes_root_hkey
, L
"Wow6432Node", access
, &hkey
))
286 static LSTATUS
open_classes_key(HKEY hkey
, const WCHAR
*name
, REGSAM access
, HKEY
*retkey
)
288 OBJECT_ATTRIBUTES attr
;
289 UNICODE_STRING nameW
;
291 if (!(hkey
= get_classes_root_hkey(hkey
, access
)))
292 return ERROR_INVALID_HANDLE
;
294 attr
.Length
= sizeof(attr
);
295 attr
.RootDirectory
= hkey
;
296 attr
.ObjectName
= &nameW
;
298 attr
.SecurityDescriptor
= NULL
;
299 attr
.SecurityQualityOfService
= NULL
;
300 RtlInitUnicodeString( &nameW
, name
);
302 return RtlNtStatusToDosError(NtOpenKey((HANDLE
*)retkey
, access
, &attr
));
305 HRESULT
open_key_for_clsid(REFCLSID clsid
, const WCHAR
*keyname
, REGSAM access
, HKEY
*subkey
)
307 static const WCHAR clsidW
[] = L
"CLSID\\";
308 WCHAR path
[CHARS_IN_GUID
+ ARRAY_SIZE(clsidW
) - 1];
312 lstrcpyW(path
, clsidW
);
313 StringFromGUID2(clsid
, path
+ lstrlenW(clsidW
), CHARS_IN_GUID
);
314 res
= open_classes_key(HKEY_CLASSES_ROOT
, path
, access
, &key
);
315 if (res
== ERROR_FILE_NOT_FOUND
)
316 return REGDB_E_CLASSNOTREG
;
317 else if (res
!= ERROR_SUCCESS
)
318 return REGDB_E_READREGDB
;
326 res
= open_classes_key(key
, keyname
, access
, subkey
);
328 if (res
== ERROR_FILE_NOT_FOUND
)
329 return REGDB_E_KEYMISSING
;
330 else if (res
!= ERROR_SUCCESS
)
331 return REGDB_E_READREGDB
;
336 /* open HKCR\\AppId\\{string form of appid clsid} key */
337 HRESULT
open_appidkey_from_clsid(REFCLSID clsid
, REGSAM access
, HKEY
*subkey
)
339 static const WCHAR appidkeyW
[] = L
"AppId\\";
341 WCHAR buf
[CHARS_IN_GUID
];
342 WCHAR keyname
[ARRAY_SIZE(appidkeyW
) + CHARS_IN_GUID
];
348 /* read the AppID value under the class's key */
349 hr
= open_key_for_clsid(clsid
, NULL
, access
, &hkey
);
354 res
= RegQueryValueExW(hkey
, L
"AppId", NULL
, &type
, (LPBYTE
)buf
, &size
);
356 if (res
== ERROR_FILE_NOT_FOUND
)
357 return REGDB_E_KEYMISSING
;
358 else if (res
!= ERROR_SUCCESS
|| type
!=REG_SZ
)
359 return REGDB_E_READREGDB
;
361 lstrcpyW(keyname
, appidkeyW
);
362 lstrcatW(keyname
, buf
);
363 res
= open_classes_key(HKEY_CLASSES_ROOT
, keyname
, access
, subkey
);
364 if (res
== ERROR_FILE_NOT_FOUND
)
365 return REGDB_E_KEYMISSING
;
366 else if (res
!= ERROR_SUCCESS
)
367 return REGDB_E_READREGDB
;
372 /***********************************************************************
373 * InternalIsProcessInitialized (combase.@)
375 BOOL WINAPI
InternalIsProcessInitialized(void)
377 struct apartment
*apt
;
379 if (!(apt
= apartment_get_current_or_mta()))
381 apartment_release(apt
);
386 /***********************************************************************
387 * InternalTlsAllocData (combase.@)
389 HRESULT WINAPI
InternalTlsAllocData(struct tlsdata
**data
)
391 if (!(*data
= calloc(1, sizeof(**data
))))
392 return E_OUTOFMEMORY
;
394 list_init(&(*data
)->spies
);
395 NtCurrentTeb()->ReservedForOle
= *data
;
400 static void com_cleanup_tlsdata(void)
402 struct tlsdata
*tlsdata
= NtCurrentTeb()->ReservedForOle
;
403 struct init_spy
*cursor
, *cursor2
;
409 apartment_release(tlsdata
->apt
);
410 if (tlsdata
->implicit_mta_cookie
)
411 apartment_decrement_mta_usage(tlsdata
->implicit_mta_cookie
);
413 if (tlsdata
->errorinfo
)
414 IErrorInfo_Release(tlsdata
->errorinfo
);
416 IUnknown_Release(tlsdata
->state
);
418 LIST_FOR_EACH_ENTRY_SAFE(cursor
, cursor2
, &tlsdata
->spies
, struct init_spy
, entry
)
420 list_remove(&cursor
->entry
);
422 IInitializeSpy_Release(cursor
->spy
);
426 if (tlsdata
->context_token
)
427 IObjContext_Release(tlsdata
->context_token
);
430 NtCurrentTeb()->ReservedForOle
= NULL
;
433 struct global_options
435 IGlobalOptions IGlobalOptions_iface
;
439 static inline struct global_options
*impl_from_IGlobalOptions(IGlobalOptions
*iface
)
441 return CONTAINING_RECORD(iface
, struct global_options
, IGlobalOptions_iface
);
444 static HRESULT WINAPI
global_options_QueryInterface(IGlobalOptions
*iface
, REFIID riid
, void **ppv
)
446 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
448 if (IsEqualGUID(&IID_IGlobalOptions
, riid
) || IsEqualGUID(&IID_IUnknown
, riid
))
455 return E_NOINTERFACE
;
458 IUnknown_AddRef((IUnknown
*)*ppv
);
462 static ULONG WINAPI
global_options_AddRef(IGlobalOptions
*iface
)
464 struct global_options
*options
= impl_from_IGlobalOptions(iface
);
465 LONG refcount
= InterlockedIncrement(&options
->refcount
);
467 TRACE("%p, refcount %ld.\n", iface
, refcount
);
472 static ULONG WINAPI
global_options_Release(IGlobalOptions
*iface
)
474 struct global_options
*options
= impl_from_IGlobalOptions(iface
);
475 LONG refcount
= InterlockedDecrement(&options
->refcount
);
477 TRACE("%p, refcount %ld.\n", iface
, refcount
);
485 static HRESULT WINAPI
global_options_Set(IGlobalOptions
*iface
, GLOBALOPT_PROPERTIES property
, ULONG_PTR value
)
487 FIXME("%p, %u, %Ix.\n", iface
, property
, value
);
492 static HRESULT WINAPI
global_options_Query(IGlobalOptions
*iface
, GLOBALOPT_PROPERTIES property
, ULONG_PTR
*value
)
494 TRACE("%p, %u, %p.\n", iface
, property
, value
);
496 if (property
< COMGLB_EXCEPTION_HANDLING
|| property
> COMGLB_PROPERTIES_RESERVED3
)
499 *value
= global_options
[property
];
504 static const IGlobalOptionsVtbl global_options_vtbl
=
506 global_options_QueryInterface
,
507 global_options_AddRef
,
508 global_options_Release
,
513 static HRESULT WINAPI
class_factory_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **ppv
)
515 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppv
);
517 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IClassFactory
))
524 return E_NOINTERFACE
;
527 static ULONG WINAPI
class_factory_AddRef(IClassFactory
*iface
)
532 static ULONG WINAPI
class_factory_Release(IClassFactory
*iface
)
537 static HRESULT WINAPI
class_factory_LockServer(IClassFactory
*iface
, BOOL fLock
)
539 TRACE("%d\n", fLock
);
544 static HRESULT WINAPI
global_options_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **ppv
)
546 struct global_options
*object
;
549 TRACE("%p, %s, %p.\n", outer
, debugstr_guid(riid
), ppv
);
554 if (!(object
= malloc(sizeof(*object
))))
555 return E_OUTOFMEMORY
;
556 object
->IGlobalOptions_iface
.lpVtbl
= &global_options_vtbl
;
557 object
->refcount
= 1;
559 hr
= IGlobalOptions_QueryInterface(&object
->IGlobalOptions_iface
, riid
, ppv
);
560 IGlobalOptions_Release(&object
->IGlobalOptions_iface
);
564 static const IClassFactoryVtbl global_options_factory_vtbl
=
566 class_factory_QueryInterface
,
567 class_factory_AddRef
,
568 class_factory_Release
,
569 global_options_CreateInstance
,
570 class_factory_LockServer
573 static IClassFactory global_options_factory
= { &global_options_factory_vtbl
};
575 static HRESULT
get_builtin_class_factory(REFCLSID rclsid
, REFIID riid
, void **obj
)
577 if (IsEqualCLSID(rclsid
, &CLSID_GlobalOptions
))
578 return IClassFactory_QueryInterface(&global_options_factory
, riid
, obj
);
582 /***********************************************************************
583 * FreePropVariantArray (combase.@)
585 HRESULT WINAPI
FreePropVariantArray(ULONG count
, PROPVARIANT
*rgvars
)
589 TRACE("%lu, %p.\n", count
, rgvars
);
594 for (i
= 0; i
< count
; ++i
)
595 PropVariantClear(&rgvars
[i
]);
600 static HRESULT
propvar_validatetype(VARTYPE vt
)
632 case VT_STREAMED_OBJECT
:
633 case VT_STORED_OBJECT
:
637 case VT_I1
|VT_VECTOR
:
638 case VT_I2
|VT_VECTOR
:
639 case VT_I4
|VT_VECTOR
:
640 case VT_I8
|VT_VECTOR
:
641 case VT_R4
|VT_VECTOR
:
642 case VT_R8
|VT_VECTOR
:
643 case VT_CY
|VT_VECTOR
:
644 case VT_DATE
|VT_VECTOR
:
645 case VT_BSTR
|VT_VECTOR
:
646 case VT_ERROR
|VT_VECTOR
:
647 case VT_BOOL
|VT_VECTOR
:
648 case VT_VARIANT
|VT_VECTOR
:
649 case VT_UI1
|VT_VECTOR
:
650 case VT_UI2
|VT_VECTOR
:
651 case VT_UI4
|VT_VECTOR
:
652 case VT_UI8
|VT_VECTOR
:
653 case VT_LPSTR
|VT_VECTOR
:
654 case VT_LPWSTR
|VT_VECTOR
:
655 case VT_FILETIME
|VT_VECTOR
:
656 case VT_CF
|VT_VECTOR
:
657 case VT_CLSID
|VT_VECTOR
:
659 case VT_ARRAY
|VT_UI1
:
661 case VT_ARRAY
|VT_UI2
:
663 case VT_ARRAY
|VT_UI4
:
664 case VT_ARRAY
|VT_INT
:
665 case VT_ARRAY
|VT_UINT
:
669 case VT_ARRAY
|VT_DATE
:
670 case VT_ARRAY
|VT_BSTR
:
671 case VT_ARRAY
|VT_BOOL
:
672 case VT_ARRAY
|VT_DECIMAL
:
673 case VT_ARRAY
|VT_DISPATCH
:
674 case VT_ARRAY
|VT_UNKNOWN
:
675 case VT_ARRAY
|VT_ERROR
:
676 case VT_ARRAY
|VT_VARIANT
:
679 WARN("Bad type %d\n", vt
);
680 return STG_E_INVALIDPARAMETER
;
683 static void propvar_free_cf_array(ULONG count
, CLIPDATA
*data
)
686 for (i
= 0; i
< count
; ++i
)
687 CoTaskMemFree(data
[i
].pClipData
);
690 /***********************************************************************
691 * PropVariantClear (combase.@)
693 HRESULT WINAPI
PropVariantClear(PROPVARIANT
*pvar
)
697 TRACE("%p.\n", pvar
);
702 hr
= propvar_validatetype(pvar
->vt
);
705 memset(pvar
, 0, sizeof(*pvar
));
735 case VT_STREAMED_OBJECT
:
737 case VT_STORED_OBJECT
:
739 IStream_Release(pvar
->pStream
);
744 /* pick an arbitrary typed pointer - we don't care about the type
745 * as we are just freeing it */
746 CoTaskMemFree(pvar
->puuid
);
750 CoTaskMemFree(pvar
->blob
.pBlobData
);
753 SysFreeString(pvar
->bstrVal
);
758 propvar_free_cf_array(1, pvar
->pclipdata
);
759 CoTaskMemFree(pvar
->pclipdata
);
763 if (pvar
->vt
& VT_VECTOR
)
767 switch (pvar
->vt
& ~VT_VECTOR
)
770 FreePropVariantArray(pvar
->capropvar
.cElems
, pvar
->capropvar
.pElems
);
773 propvar_free_cf_array(pvar
->caclipdata
.cElems
, pvar
->caclipdata
.pElems
);
776 for (i
= 0; i
< pvar
->cabstr
.cElems
; i
++)
777 SysFreeString(pvar
->cabstr
.pElems
[i
]);
780 for (i
= 0; i
< pvar
->calpstr
.cElems
; i
++)
781 CoTaskMemFree(pvar
->calpstr
.pElems
[i
]);
784 for (i
= 0; i
< pvar
->calpwstr
.cElems
; i
++)
785 CoTaskMemFree(pvar
->calpwstr
.pElems
[i
]);
788 if (pvar
->vt
& ~VT_VECTOR
)
790 /* pick an arbitrary VT_VECTOR structure - they all have the same
792 CoTaskMemFree(pvar
->capropvar
.pElems
);
795 else if (pvar
->vt
& VT_ARRAY
)
796 hr
= SafeArrayDestroy(pvar
->parray
);
799 WARN("Invalid/unsupported type %d\n", pvar
->vt
);
800 hr
= STG_E_INVALIDPARAMETER
;
804 memset(pvar
, 0, sizeof(*pvar
));
808 /***********************************************************************
809 * PropVariantCopy (combase.@)
811 HRESULT WINAPI
PropVariantCopy(PROPVARIANT
*pvarDest
, const PROPVARIANT
*pvarSrc
)
816 TRACE("%p, %p vt %04x.\n", pvarDest
, pvarSrc
, pvarSrc
->vt
);
818 hr
= propvar_validatetype(pvarSrc
->vt
);
820 return DISP_E_BADVARTYPE
;
822 /* this will deal with most cases */
823 *pvarDest
= *pvarSrc
;
851 case VT_STREAMED_OBJECT
:
853 case VT_STORED_OBJECT
:
854 if (pvarDest
->pStream
)
855 IStream_AddRef(pvarDest
->pStream
);
858 pvarDest
->puuid
= CoTaskMemAlloc(sizeof(CLSID
));
859 *pvarDest
->puuid
= *pvarSrc
->puuid
;
864 len
= strlen(pvarSrc
->pszVal
);
865 pvarDest
->pszVal
= CoTaskMemAlloc((len
+1)*sizeof(CHAR
));
866 CopyMemory(pvarDest
->pszVal
, pvarSrc
->pszVal
, (len
+1)*sizeof(CHAR
));
870 if (pvarSrc
->pwszVal
)
872 len
= lstrlenW(pvarSrc
->pwszVal
);
873 pvarDest
->pwszVal
= CoTaskMemAlloc((len
+1)*sizeof(WCHAR
));
874 CopyMemory(pvarDest
->pwszVal
, pvarSrc
->pwszVal
, (len
+1)*sizeof(WCHAR
));
879 if (pvarSrc
->blob
.pBlobData
)
881 len
= pvarSrc
->blob
.cbSize
;
882 pvarDest
->blob
.pBlobData
= CoTaskMemAlloc(len
);
883 CopyMemory(pvarDest
->blob
.pBlobData
, pvarSrc
->blob
.pBlobData
, len
);
887 pvarDest
->bstrVal
= SysAllocString(pvarSrc
->bstrVal
);
890 if (pvarSrc
->pclipdata
)
892 len
= pvarSrc
->pclipdata
->cbSize
- sizeof(pvarSrc
->pclipdata
->ulClipFmt
);
893 pvarDest
->pclipdata
= CoTaskMemAlloc(sizeof (CLIPDATA
));
894 pvarDest
->pclipdata
->cbSize
= pvarSrc
->pclipdata
->cbSize
;
895 pvarDest
->pclipdata
->ulClipFmt
= pvarSrc
->pclipdata
->ulClipFmt
;
896 pvarDest
->pclipdata
->pClipData
= CoTaskMemAlloc(len
);
897 CopyMemory(pvarDest
->pclipdata
->pClipData
, pvarSrc
->pclipdata
->pClipData
, len
);
901 if (pvarSrc
->vt
& VT_VECTOR
)
906 switch (pvarSrc
->vt
& ~VT_VECTOR
)
908 case VT_I1
: elemSize
= sizeof(pvarSrc
->cVal
); break;
909 case VT_UI1
: elemSize
= sizeof(pvarSrc
->bVal
); break;
910 case VT_I2
: elemSize
= sizeof(pvarSrc
->iVal
); break;
911 case VT_UI2
: elemSize
= sizeof(pvarSrc
->uiVal
); break;
912 case VT_BOOL
: elemSize
= sizeof(pvarSrc
->boolVal
); break;
913 case VT_I4
: elemSize
= sizeof(pvarSrc
->lVal
); break;
914 case VT_UI4
: elemSize
= sizeof(pvarSrc
->ulVal
); break;
915 case VT_R4
: elemSize
= sizeof(pvarSrc
->fltVal
); break;
916 case VT_R8
: elemSize
= sizeof(pvarSrc
->dblVal
); break;
917 case VT_ERROR
: elemSize
= sizeof(pvarSrc
->scode
); break;
918 case VT_I8
: elemSize
= sizeof(pvarSrc
->hVal
); break;
919 case VT_UI8
: elemSize
= sizeof(pvarSrc
->uhVal
); break;
920 case VT_CY
: elemSize
= sizeof(pvarSrc
->cyVal
); break;
921 case VT_DATE
: elemSize
= sizeof(pvarSrc
->date
); break;
922 case VT_FILETIME
: elemSize
= sizeof(pvarSrc
->filetime
); break;
923 case VT_CLSID
: elemSize
= sizeof(*pvarSrc
->puuid
); break;
924 case VT_CF
: elemSize
= sizeof(*pvarSrc
->pclipdata
); break;
925 case VT_BSTR
: elemSize
= sizeof(pvarSrc
->bstrVal
); break;
926 case VT_LPSTR
: elemSize
= sizeof(pvarSrc
->pszVal
); break;
927 case VT_LPWSTR
: elemSize
= sizeof(pvarSrc
->pwszVal
); break;
928 case VT_VARIANT
: elemSize
= sizeof(*pvarSrc
->pvarVal
); break;
931 FIXME("Invalid element type: %ul\n", pvarSrc
->vt
& ~VT_VECTOR
);
934 len
= pvarSrc
->capropvar
.cElems
;
935 pvarDest
->capropvar
.pElems
= len
? CoTaskMemAlloc(len
* elemSize
) : NULL
;
936 if (pvarSrc
->vt
== (VT_VECTOR
| VT_VARIANT
))
938 for (i
= 0; i
< len
; i
++)
939 PropVariantCopy(&pvarDest
->capropvar
.pElems
[i
], &pvarSrc
->capropvar
.pElems
[i
]);
941 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_CF
))
943 FIXME("Copy clipformats\n");
945 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_BSTR
))
947 for (i
= 0; i
< len
; i
++)
948 pvarDest
->cabstr
.pElems
[i
] = SysAllocString(pvarSrc
->cabstr
.pElems
[i
]);
950 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_LPSTR
))
953 for (i
= 0; i
< len
; i
++)
955 strLen
= lstrlenA(pvarSrc
->calpstr
.pElems
[i
]) + 1;
956 pvarDest
->calpstr
.pElems
[i
] = CoTaskMemAlloc(strLen
);
957 memcpy(pvarDest
->calpstr
.pElems
[i
],
958 pvarSrc
->calpstr
.pElems
[i
], strLen
);
961 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_LPWSTR
))
964 for (i
= 0; i
< len
; i
++)
966 strLen
= (lstrlenW(pvarSrc
->calpwstr
.pElems
[i
]) + 1) *
968 pvarDest
->calpstr
.pElems
[i
] = CoTaskMemAlloc(strLen
);
969 memcpy(pvarDest
->calpstr
.pElems
[i
],
970 pvarSrc
->calpstr
.pElems
[i
], strLen
);
974 CopyMemory(pvarDest
->capropvar
.pElems
, pvarSrc
->capropvar
.pElems
, len
* elemSize
);
976 else if (pvarSrc
->vt
& VT_ARRAY
)
978 pvarDest
->uhVal
.QuadPart
= 0;
979 return SafeArrayCopy(pvarSrc
->parray
, &pvarDest
->parray
);
982 WARN("Invalid/unsupported type %d\n", pvarSrc
->vt
);
988 /***********************************************************************
989 * CoFileTimeNow (combase.@)
991 HRESULT WINAPI
CoFileTimeNow(FILETIME
*filetime
)
993 GetSystemTimeAsFileTime(filetime
);
997 /******************************************************************************
998 * CoCreateGuid (combase.@)
1000 HRESULT WINAPI
CoCreateGuid(GUID
*guid
)
1004 if (!guid
) return E_INVALIDARG
;
1006 status
= UuidCreate(guid
);
1007 if (status
== RPC_S_OK
|| status
== RPC_S_UUID_LOCAL_ONLY
) return S_OK
;
1008 return HRESULT_FROM_WIN32(status
);
1011 /******************************************************************************
1012 * CoQueryProxyBlanket (combase.@)
1014 HRESULT WINAPI
CoQueryProxyBlanket(IUnknown
*proxy
, DWORD
*authn_service
,
1015 DWORD
*authz_service
, OLECHAR
**servername
, DWORD
*authn_level
,
1016 DWORD
*imp_level
, void **auth_info
, DWORD
*capabilities
)
1018 IClientSecurity
*client_security
;
1021 TRACE("%p, %p, %p, %p, %p, %p, %p, %p.\n", proxy
, authn_service
, authz_service
, servername
, authn_level
, imp_level
,
1022 auth_info
, capabilities
);
1024 hr
= IUnknown_QueryInterface(proxy
, &IID_IClientSecurity
, (void **)&client_security
);
1027 hr
= IClientSecurity_QueryBlanket(client_security
, proxy
, authn_service
, authz_service
, servername
,
1028 authn_level
, imp_level
, auth_info
, capabilities
);
1029 IClientSecurity_Release(client_security
);
1032 if (FAILED(hr
)) ERR("-- failed with %#lx.\n", hr
);
1036 /******************************************************************************
1037 * CoSetProxyBlanket (combase.@)
1039 HRESULT WINAPI
CoSetProxyBlanket(IUnknown
*proxy
, DWORD authn_service
, DWORD authz_service
,
1040 OLECHAR
*servername
, DWORD authn_level
, DWORD imp_level
, void *auth_info
, DWORD capabilities
)
1042 IClientSecurity
*client_security
;
1045 TRACE("%p, %lu, %lu, %p, %lu, %lu, %p, %#lx.\n", proxy
, authn_service
, authz_service
, servername
,
1046 authn_level
, imp_level
, auth_info
, capabilities
);
1048 hr
= IUnknown_QueryInterface(proxy
, &IID_IClientSecurity
, (void **)&client_security
);
1051 hr
= IClientSecurity_SetBlanket(client_security
, proxy
, authn_service
, authz_service
, servername
, authn_level
,
1052 imp_level
, auth_info
, capabilities
);
1053 IClientSecurity_Release(client_security
);
1056 if (FAILED(hr
)) ERR("-- failed with %#lx.\n", hr
);
1060 /***********************************************************************
1061 * CoCopyProxy (combase.@)
1063 HRESULT WINAPI
CoCopyProxy(IUnknown
*proxy
, IUnknown
**proxy_copy
)
1065 IClientSecurity
*client_security
;
1068 TRACE("%p, %p.\n", proxy
, proxy_copy
);
1070 hr
= IUnknown_QueryInterface(proxy
, &IID_IClientSecurity
, (void **)&client_security
);
1073 hr
= IClientSecurity_CopyProxy(client_security
, proxy
, proxy_copy
);
1074 IClientSecurity_Release(client_security
);
1077 if (FAILED(hr
)) ERR("-- failed with %#lx.\n", hr
);
1081 /***********************************************************************
1082 * CoQueryClientBlanket (combase.@)
1084 HRESULT WINAPI
CoQueryClientBlanket(DWORD
*authn_service
, DWORD
*authz_service
, OLECHAR
**servername
,
1085 DWORD
*authn_level
, DWORD
*imp_level
, RPC_AUTHZ_HANDLE
*privs
, DWORD
*capabilities
)
1087 IServerSecurity
*server_security
;
1090 TRACE("%p, %p, %p, %p, %p, %p, %p.\n", authn_service
, authz_service
, servername
, authn_level
, imp_level
,
1091 privs
, capabilities
);
1093 hr
= CoGetCallContext(&IID_IServerSecurity
, (void **)&server_security
);
1096 hr
= IServerSecurity_QueryBlanket(server_security
, authn_service
, authz_service
, servername
, authn_level
,
1097 imp_level
, privs
, capabilities
);
1098 IServerSecurity_Release(server_security
);
1104 /***********************************************************************
1105 * CoImpersonateClient (combase.@)
1107 HRESULT WINAPI
CoImpersonateClient(void)
1109 IServerSecurity
*server_security
;
1114 hr
= CoGetCallContext(&IID_IServerSecurity
, (void **)&server_security
);
1117 hr
= IServerSecurity_ImpersonateClient(server_security
);
1118 IServerSecurity_Release(server_security
);
1124 /***********************************************************************
1125 * CoRevertToSelf (combase.@)
1127 HRESULT WINAPI
CoRevertToSelf(void)
1129 IServerSecurity
*server_security
;
1134 hr
= CoGetCallContext(&IID_IServerSecurity
, (void **)&server_security
);
1137 hr
= IServerSecurity_RevertToSelf(server_security
);
1138 IServerSecurity_Release(server_security
);
1144 /***********************************************************************
1145 * CoInitializeSecurity (combase.@)
1147 HRESULT WINAPI
CoInitializeSecurity(PSECURITY_DESCRIPTOR sd
, LONG cAuthSvc
,
1148 SOLE_AUTHENTICATION_SERVICE
*asAuthSvc
, void *reserved1
, DWORD authn_level
,
1149 DWORD imp_level
, void *reserved2
, DWORD capabilities
, void *reserved3
)
1151 FIXME("%p, %ld, %p, %p, %ld, %ld, %p, %ld, %p stub\n", sd
, cAuthSvc
, asAuthSvc
, reserved1
, authn_level
,
1152 imp_level
, reserved2
, capabilities
, reserved3
);
1157 /***********************************************************************
1158 * CoGetObjectContext (combase.@)
1160 HRESULT WINAPI
CoGetObjectContext(REFIID riid
, void **ppv
)
1162 IObjContext
*context
;
1165 TRACE("%s, %p.\n", debugstr_guid(riid
), ppv
);
1168 hr
= CoGetContextToken((ULONG_PTR
*)&context
);
1172 return IObjContext_QueryInterface(context
, riid
, ppv
);
1175 /***********************************************************************
1176 * CoGetDefaultContext (combase.@)
1178 HRESULT WINAPI
CoGetDefaultContext(APTTYPE type
, REFIID riid
, void **obj
)
1180 FIXME("%d, %s, %p stub\n", type
, debugstr_guid(riid
), obj
);
1182 return E_NOINTERFACE
;
1185 /***********************************************************************
1186 * CoGetCallState (combase.@)
1188 HRESULT WINAPI
CoGetCallState(int arg1
, ULONG
*arg2
)
1190 FIXME("%d, %p.\n", arg1
, arg2
);
1195 /***********************************************************************
1196 * CoGetActivationState (combase.@)
1198 HRESULT WINAPI
CoGetActivationState(GUID guid
, DWORD arg2
, DWORD
*arg3
)
1200 FIXME("%s, %lx, %p.\n", debugstr_guid(&guid
), arg2
, arg3
);
1205 /******************************************************************************
1206 * CoGetTreatAsClass (combase.@)
1208 HRESULT WINAPI
CoGetTreatAsClass(REFCLSID clsidOld
, CLSID
*clsidNew
)
1210 WCHAR buffW
[CHARS_IN_GUID
];
1211 LONG len
= sizeof(buffW
);
1215 TRACE("%s, %p.\n", debugstr_guid(clsidOld
), clsidNew
);
1217 if (!clsidOld
|| !clsidNew
)
1218 return E_INVALIDARG
;
1220 *clsidNew
= *clsidOld
;
1222 hr
= open_key_for_clsid(clsidOld
, L
"TreatAs", KEY_READ
, &hkey
);
1229 if (RegQueryValueW(hkey
, NULL
, buffW
, &len
))
1235 hr
= CLSIDFromString(buffW
, clsidNew
);
1237 ERR("Failed to get CLSID from string %s, hr %#lx.\n", debugstr_w(buffW
), hr
);
1239 if (hkey
) RegCloseKey(hkey
);
1243 /******************************************************************************
1244 * ProgIDFromCLSID (combase.@)
1246 HRESULT WINAPI DECLSPEC_HOTPATCH
ProgIDFromCLSID(REFCLSID clsid
, LPOLESTR
*progid
)
1248 ACTCTX_SECTION_KEYED_DATA data
;
1251 REGSAM opposite
= (sizeof(void *) > sizeof(int)) ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
;
1256 return E_INVALIDARG
;
1260 data
.cbSize
= sizeof(data
);
1261 if (FindActCtxSectionGuid(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
,
1264 struct comclassredirect_data
*comclass
= (struct comclassredirect_data
*)data
.lpData
;
1265 if (comclass
->progid_len
)
1269 *progid
= CoTaskMemAlloc(comclass
->progid_len
+ sizeof(WCHAR
));
1270 if (!*progid
) return E_OUTOFMEMORY
;
1272 ptrW
= (WCHAR
*)((BYTE
*)comclass
+ comclass
->progid_offset
);
1273 memcpy(*progid
, ptrW
, comclass
->progid_len
+ sizeof(WCHAR
));
1277 return REGDB_E_CLASSNOTREG
;
1280 hr
= open_key_for_clsid(clsid
, L
"ProgID", KEY_READ
, &hkey
);
1281 if (FAILED(hr
) && (opposite
== KEY_WOW64_32KEY
|| (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)))
1283 hr
= open_key_for_clsid(clsid
, L
"ProgID", opposite
| KEY_READ
, &hkey
);
1288 if (RegQueryValueW(hkey
, NULL
, NULL
, &progidlen
))
1289 hr
= REGDB_E_CLASSNOTREG
;
1293 *progid
= CoTaskMemAlloc(progidlen
* sizeof(WCHAR
));
1296 if (RegQueryValueW(hkey
, NULL
, *progid
, &progidlen
))
1298 hr
= REGDB_E_CLASSNOTREG
;
1299 CoTaskMemFree(*progid
);
1311 static inline BOOL
is_valid_hex(WCHAR c
)
1313 if (!(((c
>= '0') && (c
<= '9')) ||
1314 ((c
>= 'a') && (c
<= 'f')) ||
1315 ((c
>= 'A') && (c
<= 'F'))))
1320 static const BYTE guid_conv_table
[256] =
1322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
1323 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
1324 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
1325 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
1326 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
1327 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
1328 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
1331 static BOOL
guid_from_string(LPCWSTR s
, GUID
*id
)
1335 if (!s
|| s
[0] != '{')
1337 memset(id
, 0, sizeof(*id
));
1338 if (!s
) return TRUE
;
1342 TRACE("%s -> %p\n", debugstr_w(s
), id
);
1344 /* In form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
1347 for (i
= 1; i
< 9; ++i
)
1349 if (!is_valid_hex(s
[i
])) return FALSE
;
1350 id
->Data1
= (id
->Data1
<< 4) | guid_conv_table
[s
[i
]];
1352 if (s
[9] != '-') return FALSE
;
1355 for (i
= 10; i
< 14; ++i
)
1357 if (!is_valid_hex(s
[i
])) return FALSE
;
1358 id
->Data2
= (id
->Data2
<< 4) | guid_conv_table
[s
[i
]];
1360 if (s
[14] != '-') return FALSE
;
1363 for (i
= 15; i
< 19; ++i
)
1365 if (!is_valid_hex(s
[i
])) return FALSE
;
1366 id
->Data3
= (id
->Data3
<< 4) | guid_conv_table
[s
[i
]];
1368 if (s
[19] != '-') return FALSE
;
1370 for (i
= 20; i
< 37; i
+= 2)
1374 if (s
[i
] != '-') return FALSE
;
1377 if (!is_valid_hex(s
[i
]) || !is_valid_hex(s
[i
+ 1])) return FALSE
;
1378 id
->Data4
[(i
- 20) / 2] = guid_conv_table
[s
[i
]] << 4 | guid_conv_table
[s
[i
+ 1]];
1381 if (s
[37] == '}' && s
[38] == '\0')
1387 static HRESULT
clsid_from_string_reg(LPCOLESTR progid
, CLSID
*clsid
)
1389 WCHAR buf2
[CHARS_IN_GUID
];
1390 LONG buf2len
= sizeof(buf2
);
1394 memset(clsid
, 0, sizeof(*clsid
));
1395 buf
= malloc((lstrlenW(progid
) + 8) * sizeof(WCHAR
));
1396 if (!buf
) return E_OUTOFMEMORY
;
1398 lstrcpyW(buf
, progid
);
1399 lstrcatW(buf
, L
"\\CLSID");
1400 if (open_classes_key(HKEY_CLASSES_ROOT
, buf
, MAXIMUM_ALLOWED
, &xhkey
))
1403 WARN("couldn't open key for ProgID %s\n", debugstr_w(progid
));
1404 return CO_E_CLASSSTRING
;
1408 if (RegQueryValueW(xhkey
, NULL
, buf2
, &buf2len
))
1411 WARN("couldn't query clsid value for ProgID %s\n", debugstr_w(progid
));
1412 return CO_E_CLASSSTRING
;
1415 return guid_from_string(buf2
, clsid
) ? S_OK
: CO_E_CLASSSTRING
;
1418 /******************************************************************************
1419 * CLSIDFromProgID (combase.@)
1421 HRESULT WINAPI DECLSPEC_HOTPATCH
CLSIDFromProgID(LPCOLESTR progid
, CLSID
*clsid
)
1423 ACTCTX_SECTION_KEYED_DATA data
;
1425 if (!progid
|| !clsid
)
1426 return E_INVALIDARG
;
1428 data
.cbSize
= sizeof(data
);
1429 if (FindActCtxSectionStringW(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
,
1432 struct progidredirect_data
*progiddata
= (struct progidredirect_data
*)data
.lpData
;
1433 CLSID
*alias
= (CLSID
*)((BYTE
*)data
.lpSectionBase
+ progiddata
->clsid_offset
);
1438 return clsid_from_string_reg(progid
, clsid
);
1441 /******************************************************************************
1442 * CLSIDFromProgIDEx (combase.@)
1444 HRESULT WINAPI
CLSIDFromProgIDEx(LPCOLESTR progid
, CLSID
*clsid
)
1446 FIXME("%s, %p: semi-stub\n", debugstr_w(progid
), clsid
);
1448 return CLSIDFromProgID(progid
, clsid
);
1451 /******************************************************************************
1452 * CLSIDFromString (combase.@)
1454 HRESULT WINAPI
CLSIDFromString(LPCOLESTR str
, LPCLSID clsid
)
1460 return E_INVALIDARG
;
1462 if (guid_from_string(str
, clsid
))
1465 /* It appears a ProgID is also valid */
1466 hr
= clsid_from_string_reg(str
, &tmp_id
);
1473 /******************************************************************************
1474 * IIDFromString (combase.@)
1476 HRESULT WINAPI
IIDFromString(LPCOLESTR str
, IID
*iid
)
1478 TRACE("%s, %p\n", debugstr_w(str
), iid
);
1482 memset(iid
, 0, sizeof(*iid
));
1486 /* length mismatch is a special case */
1487 if (lstrlenW(str
) + 1 != CHARS_IN_GUID
)
1488 return E_INVALIDARG
;
1491 return CO_E_IIDSTRING
;
1493 return guid_from_string(str
, iid
) ? S_OK
: CO_E_IIDSTRING
;
1496 /******************************************************************************
1497 * StringFromCLSID (combase.@)
1499 HRESULT WINAPI
StringFromCLSID(REFCLSID clsid
, LPOLESTR
*str
)
1501 if (!(*str
= CoTaskMemAlloc(CHARS_IN_GUID
* sizeof(WCHAR
)))) return E_OUTOFMEMORY
;
1502 StringFromGUID2(clsid
, *str
, CHARS_IN_GUID
);
1506 /******************************************************************************
1507 * StringFromGUID2 (combase.@)
1509 INT WINAPI
StringFromGUID2(REFGUID guid
, LPOLESTR str
, INT cmax
)
1511 if (!guid
|| cmax
< CHARS_IN_GUID
) return 0;
1512 swprintf(str
, CHARS_IN_GUID
, L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", guid
->Data1
,
1513 guid
->Data2
, guid
->Data3
, guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
1514 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
1515 return CHARS_IN_GUID
;
1518 static void init_multi_qi(DWORD count
, MULTI_QI
*mqi
, HRESULT hr
)
1522 for (i
= 0; i
< count
; i
++)
1529 static HRESULT
return_multi_qi(IUnknown
*unk
, DWORD count
, MULTI_QI
*mqi
, BOOL include_unk
)
1531 ULONG index
= 0, fetched
= 0;
1537 index
= fetched
= 1;
1540 for (; index
< count
; index
++)
1542 mqi
[index
].hr
= IUnknown_QueryInterface(unk
, mqi
[index
].pIID
, (void **)&mqi
[index
].pItf
);
1543 if (mqi
[index
].hr
== S_OK
)
1548 IUnknown_Release(unk
);
1551 return E_NOINTERFACE
;
1553 return fetched
== count
? S_OK
: CO_S_NOTALLINTERFACES
;
1556 /***********************************************************************
1557 * CoGetInstanceFromFile (combase.@)
1559 HRESULT WINAPI DECLSPEC_HOTPATCH
CoGetInstanceFromFile(COSERVERINFO
*server_info
, CLSID
*rclsid
,
1560 IUnknown
*outer
, DWORD cls_context
, DWORD grfmode
, OLECHAR
*filename
, DWORD count
,
1563 IPersistFile
*pf
= NULL
;
1564 IUnknown
*obj
= NULL
;
1568 if (!count
|| !results
)
1569 return E_INVALIDARG
;
1572 FIXME("() non-NULL server_info not supported\n");
1574 init_multi_qi(count
, results
, E_NOINTERFACE
);
1578 hr
= GetClassFile(filename
, &clsid
);
1581 ERR("Failed to get CLSID from a file.\n");
1588 hr
= CoCreateInstance(rclsid
, outer
, cls_context
, &IID_IUnknown
, (void **)&obj
);
1591 init_multi_qi(count
, results
, hr
);
1595 /* Init from file */
1596 hr
= IUnknown_QueryInterface(obj
, &IID_IPersistFile
, (void **)&pf
);
1599 init_multi_qi(count
, results
, hr
);
1600 IUnknown_Release(obj
);
1604 hr
= IPersistFile_Load(pf
, filename
, grfmode
);
1605 IPersistFile_Release(pf
);
1607 return return_multi_qi(obj
, count
, results
, FALSE
);
1610 init_multi_qi(count
, results
, hr
);
1611 IUnknown_Release(obj
);
1616 /***********************************************************************
1617 * CoGetInstanceFromIStorage (combase.@)
1619 HRESULT WINAPI
CoGetInstanceFromIStorage(COSERVERINFO
*server_info
, CLSID
*rclsid
,
1620 IUnknown
*outer
, DWORD cls_context
, IStorage
*storage
, DWORD count
, MULTI_QI
*results
)
1622 IPersistStorage
*ps
= NULL
;
1623 IUnknown
*obj
= NULL
;
1627 if (!count
|| !results
|| !storage
)
1628 return E_INVALIDARG
;
1631 FIXME("() non-NULL server_info not supported\n");
1633 init_multi_qi(count
, results
, E_NOINTERFACE
);
1637 memset(&stat
.clsid
, 0, sizeof(stat
.clsid
));
1638 hr
= IStorage_Stat(storage
, &stat
, STATFLAG_NONAME
);
1641 ERR("Failed to get CLSID from a storage.\n");
1645 rclsid
= &stat
.clsid
;
1648 hr
= CoCreateInstance(rclsid
, outer
, cls_context
, &IID_IUnknown
, (void **)&obj
);
1652 /* Init from IStorage */
1653 hr
= IUnknown_QueryInterface(obj
, &IID_IPersistStorage
, (void **)&ps
);
1655 ERR("failed to get IPersistStorage\n");
1659 IPersistStorage_Load(ps
, storage
);
1660 IPersistStorage_Release(ps
);
1663 return return_multi_qi(obj
, count
, results
, FALSE
);
1666 /***********************************************************************
1667 * CoCreateInstance (combase.@)
1669 HRESULT WINAPI DECLSPEC_HOTPATCH
CoCreateInstance(REFCLSID rclsid
, IUnknown
*outer
, DWORD cls_context
,
1670 REFIID riid
, void **obj
)
1672 MULTI_QI multi_qi
= { .pIID
= riid
};
1675 TRACE("%s, %p, %#lx, %s, %p.\n", debugstr_guid(rclsid
), outer
, cls_context
, debugstr_guid(riid
), obj
);
1680 hr
= CoCreateInstanceEx(rclsid
, outer
, cls_context
, NULL
, 1, &multi_qi
);
1681 *obj
= multi_qi
.pItf
;
1685 /***********************************************************************
1686 * CoCreateInstanceFromApp (combase.@)
1688 HRESULT WINAPI
CoCreateInstanceFromApp(REFCLSID rclsid
, IUnknown
*outer
, DWORD cls_context
,
1689 void *server_info
, ULONG count
, MULTI_QI
*results
)
1691 TRACE("%s, %p, %#lx, %p, %lu, %p\n", debugstr_guid(rclsid
), outer
, cls_context
, server_info
,
1694 return CoCreateInstanceEx(rclsid
, outer
, cls_context
| CLSCTX_APPCONTAINER
, server_info
,
1698 static HRESULT
com_get_class_object(REFCLSID rclsid
, DWORD clscontext
,
1699 COSERVERINFO
*server_info
, REFIID riid
, void **obj
)
1701 struct class_reg_data clsreg
= { 0 };
1702 HRESULT hr
= E_UNEXPECTED
;
1703 IUnknown
*registered_obj
;
1704 struct apartment
*apt
;
1707 return E_INVALIDARG
;
1711 if (!(apt
= apartment_get_current_or_mta()))
1713 ERR("apartment not initialised\n");
1714 return CO_E_NOTINITIALIZED
;
1718 FIXME("server_info name %s, authinfo %p\n", debugstr_w(server_info
->pwszName
), server_info
->pAuthInfo
);
1720 if (clscontext
& CLSCTX_INPROC_SERVER
)
1722 if (IsEqualCLSID(rclsid
, &CLSID_InProcFreeMarshaler
) ||
1723 IsEqualCLSID(rclsid
, &CLSID_GlobalOptions
) ||
1724 (!(clscontext
& CLSCTX_APPCONTAINER
) && IsEqualCLSID(rclsid
, &CLSID_ManualResetEvent
)) ||
1725 IsEqualCLSID(rclsid
, &CLSID_StdGlobalInterfaceTable
))
1727 apartment_release(apt
);
1729 if (IsEqualCLSID(rclsid
, &CLSID_GlobalOptions
))
1730 return get_builtin_class_factory(rclsid
, riid
, obj
);
1732 return Ole32DllGetClassObject(rclsid
, riid
, obj
);
1736 if (clscontext
& CLSCTX_INPROC
)
1738 ACTCTX_SECTION_KEYED_DATA data
;
1740 data
.cbSize
= sizeof(data
);
1741 /* search activation context first */
1742 if (FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
, NULL
,
1743 ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
, rclsid
, &data
))
1745 struct comclassredirect_data
*comclass
= (struct comclassredirect_data
*)data
.lpData
;
1747 clsreg
.u
.actctx
.module_name
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ comclass
->name_offset
);
1748 clsreg
.u
.actctx
.hactctx
= data
.hActCtx
;
1749 clsreg
.u
.actctx
.threading_model
= comclass
->model
;
1750 clsreg
.origin
= CLASS_REG_ACTCTX
;
1752 hr
= apartment_get_inproc_class_object(apt
, &clsreg
, &comclass
->clsid
, riid
, clscontext
, obj
);
1753 ReleaseActCtx(data
.hActCtx
);
1754 apartment_release(apt
);
1760 * First, try and see if we can't match the class ID with one of the
1761 * registered classes.
1763 if (!(clscontext
& CLSCTX_APPCONTAINER
) && (registered_obj
= com_get_registered_class_object(apt
, rclsid
, clscontext
)))
1765 hr
= IUnknown_QueryInterface(registered_obj
, riid
, obj
);
1766 IUnknown_Release(registered_obj
);
1767 apartment_release(apt
);
1771 /* First try in-process server */
1772 if (clscontext
& CLSCTX_INPROC_SERVER
)
1776 hr
= open_key_for_clsid(rclsid
, L
"InprocServer32", KEY_READ
, &hkey
);
1779 if (hr
== REGDB_E_CLASSNOTREG
)
1780 ERR("class %s not registered\n", debugstr_guid(rclsid
));
1781 else if (hr
== REGDB_E_KEYMISSING
)
1783 WARN("class %s not registered as in-proc server\n", debugstr_guid(rclsid
));
1784 hr
= REGDB_E_CLASSNOTREG
;
1790 clsreg
.u
.hkey
= hkey
;
1791 clsreg
.origin
= CLASS_REG_REGISTRY
;
1793 hr
= apartment_get_inproc_class_object(apt
, &clsreg
, rclsid
, riid
, clscontext
, obj
);
1797 /* return if we got a class, otherwise fall through to one of the
1801 apartment_release(apt
);
1806 /* Next try in-process handler */
1807 if (clscontext
& CLSCTX_INPROC_HANDLER
)
1811 hr
= open_key_for_clsid(rclsid
, L
"InprocHandler32", KEY_READ
, &hkey
);
1814 if (hr
== REGDB_E_CLASSNOTREG
)
1815 ERR("class %s not registered\n", debugstr_guid(rclsid
));
1816 else if (hr
== REGDB_E_KEYMISSING
)
1818 WARN("class %s not registered in-proc handler\n", debugstr_guid(rclsid
));
1819 hr
= REGDB_E_CLASSNOTREG
;
1825 clsreg
.u
.hkey
= hkey
;
1826 clsreg
.origin
= CLASS_REG_REGISTRY
;
1828 hr
= apartment_get_inproc_class_object(apt
, &clsreg
, rclsid
, riid
, clscontext
, obj
);
1832 /* return if we got a class, otherwise fall through to one of the
1836 apartment_release(apt
);
1840 apartment_release(apt
);
1842 /* Next try out of process */
1843 if (clscontext
& CLSCTX_LOCAL_SERVER
)
1845 hr
= rpc_get_local_class_object(rclsid
, riid
, obj
);
1850 /* Finally try remote: this requires networked DCOM (a lot of work) */
1851 if (clscontext
& CLSCTX_REMOTE_SERVER
)
1853 FIXME ("CLSCTX_REMOTE_SERVER not supported\n");
1854 hr
= REGDB_E_CLASSNOTREG
;
1858 ERR("no class object %s could be created for context %#lx\n", debugstr_guid(rclsid
), clscontext
);
1863 /***********************************************************************
1864 * CoCreateInstanceEx (combase.@)
1866 HRESULT WINAPI DECLSPEC_HOTPATCH
CoCreateInstanceEx(REFCLSID rclsid
, IUnknown
*outer
, DWORD cls_context
,
1867 COSERVERINFO
*server_info
, ULONG count
, MULTI_QI
*results
)
1869 IClassFactory
*factory
;
1870 IUnknown
*unk
= NULL
;
1874 TRACE("%s, %p, %#lx, %p, %lu, %p\n", debugstr_guid(rclsid
), outer
, cls_context
, server_info
, count
, results
);
1876 if (!count
|| !results
)
1877 return E_INVALIDARG
;
1880 FIXME("Server info is not supported.\n");
1882 init_multi_qi(count
, results
, E_NOINTERFACE
);
1885 if (!(cls_context
& CLSCTX_APPCONTAINER
))
1886 CoGetTreatAsClass(rclsid
, &clsid
);
1888 if (FAILED(hr
= com_get_class_object(&clsid
, cls_context
, NULL
, &IID_IClassFactory
, (void **)&factory
)))
1891 hr
= IClassFactory_CreateInstance(factory
, outer
, results
[0].pIID
, (void **)&unk
);
1892 IClassFactory_Release(factory
);
1895 if (hr
== CLASS_E_NOAGGREGATION
&& outer
)
1896 FIXME("Class %s does not support aggregation\n", debugstr_guid(&clsid
));
1898 FIXME("no instance created for interface %s of class %s, hr %#lx.\n",
1899 debugstr_guid(results
[0].pIID
), debugstr_guid(&clsid
), hr
);
1903 return return_multi_qi(unk
, count
, results
, TRUE
);
1906 /***********************************************************************
1907 * CoGetClassObject (combase.@)
1909 HRESULT WINAPI DECLSPEC_HOTPATCH
CoGetClassObject(REFCLSID rclsid
, DWORD clscontext
,
1910 COSERVERINFO
*server_info
, REFIID riid
, void **obj
)
1912 TRACE("%s, %#lx, %s\n", debugstr_guid(rclsid
), clscontext
, debugstr_guid(riid
));
1914 return com_get_class_object(rclsid
, clscontext
, server_info
, riid
, obj
);
1917 /***********************************************************************
1918 * CoFreeUnusedLibraries (combase.@)
1920 void WINAPI DECLSPEC_HOTPATCH
CoFreeUnusedLibraries(void)
1922 CoFreeUnusedLibrariesEx(INFINITE
, 0);
1925 /***********************************************************************
1926 * CoGetCallContext (combase.@)
1928 HRESULT WINAPI
CoGetCallContext(REFIID riid
, void **obj
)
1930 struct tlsdata
*tlsdata
;
1933 TRACE("%s, %p\n", debugstr_guid(riid
), obj
);
1935 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1938 if (!tlsdata
->call_state
)
1939 return RPC_E_CALL_COMPLETE
;
1941 return IUnknown_QueryInterface(tlsdata
->call_state
, riid
, obj
);
1944 /***********************************************************************
1945 * CoSwitchCallContext (combase.@)
1947 HRESULT WINAPI
CoSwitchCallContext(IUnknown
*context
, IUnknown
**old_context
)
1949 struct tlsdata
*tlsdata
;
1952 TRACE("%p, %p\n", context
, old_context
);
1954 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1957 /* Reference counts are not touched. */
1958 *old_context
= tlsdata
->call_state
;
1959 tlsdata
->call_state
= context
;
1964 /******************************************************************************
1965 * CoRegisterInitializeSpy (combase.@)
1967 HRESULT WINAPI
CoRegisterInitializeSpy(IInitializeSpy
*spy
, ULARGE_INTEGER
*cookie
)
1969 struct tlsdata
*tlsdata
;
1970 struct init_spy
*entry
;
1974 TRACE("%p, %p\n", spy
, cookie
);
1976 if (!spy
|| !cookie
)
1977 return E_INVALIDARG
;
1979 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1982 hr
= IInitializeSpy_QueryInterface(spy
, &IID_IInitializeSpy
, (void **)&spy
);
1986 entry
= malloc(sizeof(*entry
));
1989 IInitializeSpy_Release(spy
);
1990 return E_OUTOFMEMORY
;
1996 while (get_spy_entry(tlsdata
, id
) != NULL
)
2002 list_add_head(&tlsdata
->spies
, &entry
->entry
);
2004 cookie
->u
.HighPart
= GetCurrentThreadId();
2005 cookie
->u
.LowPart
= entry
->id
;
2010 /******************************************************************************
2011 * CoRevokeInitializeSpy (combase.@)
2013 HRESULT WINAPI
CoRevokeInitializeSpy(ULARGE_INTEGER cookie
)
2015 struct tlsdata
*tlsdata
;
2016 struct init_spy
*spy
;
2019 TRACE("%s\n", wine_dbgstr_longlong(cookie
.QuadPart
));
2021 if (cookie
.u
.HighPart
!= GetCurrentThreadId())
2022 return E_INVALIDARG
;
2024 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
2027 if (!(spy
= get_spy_entry(tlsdata
, cookie
.u
.LowPart
))) return E_INVALIDARG
;
2029 IInitializeSpy_Release(spy
->spy
);
2031 if (!tlsdata
->spies_lock
)
2033 list_remove(&spy
->entry
);
2039 static BOOL
com_peek_message(struct apartment
*apt
, MSG
*msg
)
2041 /* First try to retrieve messages for incoming COM calls to the apartment window */
2042 return (apt
->win
&& PeekMessageW(msg
, apt
->win
, 0, 0, PM_REMOVE
| PM_NOYIELD
)) ||
2043 /* Next retrieve other messages necessary for the app to remain responsive */
2044 PeekMessageW(msg
, NULL
, WM_DDE_FIRST
, WM_DDE_LAST
, PM_REMOVE
| PM_NOYIELD
) ||
2045 PeekMessageW(msg
, NULL
, 0, 0, PM_QS_PAINT
| PM_QS_SENDMESSAGE
| PM_REMOVE
| PM_NOYIELD
);
2048 /***********************************************************************
2049 * CoWaitForMultipleHandles (combase.@)
2051 HRESULT WINAPI
CoWaitForMultipleHandles(DWORD flags
, DWORD timeout
, ULONG handle_count
, HANDLE
*handles
,
2054 BOOL check_apc
= !!(flags
& COWAIT_ALERTABLE
), post_quit
= FALSE
, message_loop
;
2055 DWORD start_time
, wait_flags
= 0;
2056 struct tlsdata
*tlsdata
;
2057 struct apartment
*apt
;
2061 TRACE("%#lx, %#lx, %lu, %p, %p\n", flags
, timeout
, handle_count
, handles
, index
);
2064 return E_INVALIDARG
;
2069 return E_INVALIDARG
;
2072 return RPC_E_NO_SYNC
;
2074 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
2077 apt
= com_get_current_apt();
2078 message_loop
= apt
&& !apt
->multi_threaded
;
2080 if (flags
& COWAIT_WAITALL
)
2081 wait_flags
|= MWMO_WAITALL
;
2082 if (flags
& COWAIT_ALERTABLE
)
2083 wait_flags
|= MWMO_ALERTABLE
;
2085 start_time
= GetTickCount();
2089 DWORD now
= GetTickCount(), res
;
2091 if (now
- start_time
> timeout
)
2093 hr
= RPC_S_CALLPENDING
;
2099 TRACE("waiting for rpc completion or window message\n");
2105 res
= WaitForMultipleObjectsEx(handle_count
, handles
, !!(flags
& COWAIT_WAITALL
), 0, TRUE
);
2109 if (res
== WAIT_TIMEOUT
)
2110 res
= MsgWaitForMultipleObjectsEx(handle_count
, handles
,
2111 timeout
== INFINITE
? INFINITE
: start_time
+ timeout
- now
,
2112 QS_SENDMESSAGE
| QS_ALLPOSTMESSAGE
| QS_PAINT
, wait_flags
);
2114 if (res
== WAIT_OBJECT_0
+ handle_count
) /* messages available */
2119 /* call message filter */
2123 PENDINGTYPE pendingtype
= tlsdata
->pending_call_count_server
? PENDINGTYPE_NESTED
: PENDINGTYPE_TOPLEVEL
;
2124 DWORD be_handled
= IMessageFilter_MessagePending(apt
->filter
, 0 /* FIXME */, now
- start_time
, pendingtype
);
2126 TRACE("IMessageFilter_MessagePending returned %ld\n", be_handled
);
2130 case PENDINGMSG_CANCELCALL
:
2131 WARN("call canceled\n");
2132 hr
= RPC_E_CALL_CANCELED
;
2134 case PENDINGMSG_WAITNOPROCESS
:
2135 case PENDINGMSG_WAITDEFPROCESS
:
2137 /* FIXME: MSDN is very vague about the difference
2138 * between WAITNOPROCESS and WAITDEFPROCESS - there
2139 * appears to be none, so it is possibly a left-over
2140 * from the 16-bit world. */
2147 /* If window is NULL on apartment, peek at messages so that it will not trigger
2148 * MsgWaitForMultipleObjects next time. */
2149 PeekMessageW(NULL
, NULL
, 0, 0, PM_QS_POSTMESSAGE
| PM_NOREMOVE
| PM_NOYIELD
);
2152 /* Some apps (e.g. Visio 2010) don't handle WM_PAINT properly and loop forever,
2153 * so after processing 100 messages we go back to checking the wait handles */
2154 while (msg_count
++ < 100 && com_peek_message(apt
, &msg
))
2156 if (msg
.message
== WM_QUIT
)
2158 TRACE("Received WM_QUIT message\n");
2160 exit_code
= msg
.wParam
;
2164 TRACE("Received message whilst waiting for RPC: 0x%04x\n", msg
.message
);
2165 TranslateMessage(&msg
);
2166 DispatchMessageW(&msg
);
2174 TRACE("Waiting for rpc completion\n");
2176 res
= WaitForMultipleObjectsEx(handle_count
, handles
, !!(flags
& COWAIT_WAITALL
),
2177 (timeout
== INFINITE
) ? INFINITE
: start_time
+ timeout
- now
, !!(flags
& COWAIT_ALERTABLE
));
2183 hr
= RPC_S_CALLPENDING
;
2186 hr
= HRESULT_FROM_WIN32(GetLastError());
2194 if (post_quit
) PostQuitMessage(exit_code
);
2196 TRACE("-- %#lx\n", hr
);
2201 /******************************************************************************
2202 * CoRegisterMessageFilter (combase.@)
2204 HRESULT WINAPI
CoRegisterMessageFilter(IMessageFilter
*filter
, IMessageFilter
**ret_filter
)
2206 IMessageFilter
*old_filter
;
2207 struct apartment
*apt
;
2209 TRACE("%p, %p\n", filter
, ret_filter
);
2211 apt
= com_get_current_apt();
2213 /* Can't set a message filter in a multi-threaded apartment */
2214 if (!apt
|| apt
->multi_threaded
)
2216 WARN("Can't set message filter in MTA or uninitialized apt\n");
2217 return CO_E_NOT_SUPPORTED
;
2221 IMessageFilter_AddRef(filter
);
2223 EnterCriticalSection(&apt
->cs
);
2225 old_filter
= apt
->filter
;
2226 apt
->filter
= filter
;
2228 LeaveCriticalSection(&apt
->cs
);
2231 *ret_filter
= old_filter
;
2232 else if (old_filter
)
2233 IMessageFilter_Release(old_filter
);
2238 static void com_revoke_all_ps_clsids(void)
2240 struct registered_ps
*cur
, *cur2
;
2242 EnterCriticalSection(&cs_registered_ps
);
2244 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, ®istered_proxystubs
, struct registered_ps
, entry
)
2246 list_remove(&cur
->entry
);
2250 LeaveCriticalSection(&cs_registered_ps
);
2253 static HRESULT
get_ps_clsid_from_registry(const WCHAR
* path
, REGSAM access
, CLSID
*pclsid
)
2255 WCHAR value
[CHARS_IN_GUID
];
2261 if (open_classes_key(HKEY_CLASSES_ROOT
, path
, access
, &hkey
))
2262 return REGDB_E_IIDNOTREG
;
2264 len
= sizeof(value
);
2265 if (ERROR_SUCCESS
!= RegQueryValueExW(hkey
, NULL
, NULL
, NULL
, (BYTE
*)value
, &len
))
2266 return REGDB_E_IIDNOTREG
;
2269 if (CLSIDFromString(value
, pclsid
) != NOERROR
)
2270 return REGDB_E_IIDNOTREG
;
2275 /*****************************************************************************
2276 * CoGetPSClsid (combase.@)
2278 HRESULT WINAPI
CoGetPSClsid(REFIID riid
, CLSID
*pclsid
)
2280 static const WCHAR interfaceW
[] = L
"Interface\\";
2281 static const WCHAR psW
[] = L
"\\ProxyStubClsid32";
2282 WCHAR path
[ARRAY_SIZE(interfaceW
) - 1 + CHARS_IN_GUID
- 1 + ARRAY_SIZE(psW
)];
2283 ACTCTX_SECTION_KEYED_DATA data
;
2284 struct registered_ps
*cur
;
2285 REGSAM opposite
= (sizeof(void*) > sizeof(int)) ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
;
2289 TRACE("%s, %p\n", debugstr_guid(riid
), pclsid
);
2291 if (!InternalIsProcessInitialized())
2293 ERR("apartment not initialised\n");
2294 return CO_E_NOTINITIALIZED
;
2298 return E_INVALIDARG
;
2300 EnterCriticalSection(&cs_registered_ps
);
2302 LIST_FOR_EACH_ENTRY(cur
, ®istered_proxystubs
, struct registered_ps
, entry
)
2304 if (IsEqualIID(&cur
->iid
, riid
))
2306 *pclsid
= cur
->clsid
;
2307 LeaveCriticalSection(&cs_registered_ps
);
2312 LeaveCriticalSection(&cs_registered_ps
);
2314 data
.cbSize
= sizeof(data
);
2315 if (FindActCtxSectionGuid(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
,
2318 struct ifacepsredirect_data
*ifaceps
= (struct ifacepsredirect_data
*)data
.lpData
;
2319 *pclsid
= ifaceps
->iid
;
2323 /* Interface\\{string form of riid}\\ProxyStubClsid32 */
2324 lstrcpyW(path
, interfaceW
);
2325 StringFromGUID2(riid
, path
+ ARRAY_SIZE(interfaceW
) - 1, CHARS_IN_GUID
);
2326 lstrcpyW(path
+ ARRAY_SIZE(interfaceW
) - 1 + CHARS_IN_GUID
- 1, psW
);
2328 hr
= get_ps_clsid_from_registry(path
, KEY_READ
, pclsid
);
2329 if (FAILED(hr
) && (opposite
== KEY_WOW64_32KEY
|| (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)))
2330 hr
= get_ps_clsid_from_registry(path
, opposite
| KEY_READ
, pclsid
);
2333 TRACE("() Returning CLSID %s\n", debugstr_guid(pclsid
));
2335 WARN("No PSFactoryBuffer object is registered for IID %s\n", debugstr_guid(riid
));
2340 /*****************************************************************************
2341 * CoRegisterPSClsid (combase.@)
2343 HRESULT WINAPI
CoRegisterPSClsid(REFIID riid
, REFCLSID rclsid
)
2345 struct registered_ps
*cur
;
2347 TRACE("%s, %s\n", debugstr_guid(riid
), debugstr_guid(rclsid
));
2349 if (!InternalIsProcessInitialized())
2351 ERR("apartment not initialised\n");
2352 return CO_E_NOTINITIALIZED
;
2355 EnterCriticalSection(&cs_registered_ps
);
2357 LIST_FOR_EACH_ENTRY(cur
, ®istered_proxystubs
, struct registered_ps
, entry
)
2359 if (IsEqualIID(&cur
->iid
, riid
))
2361 cur
->clsid
= *rclsid
;
2362 LeaveCriticalSection(&cs_registered_ps
);
2367 cur
= malloc(sizeof(*cur
));
2370 LeaveCriticalSection(&cs_registered_ps
);
2371 return E_OUTOFMEMORY
;
2375 cur
->clsid
= *rclsid
;
2376 list_add_head(®istered_proxystubs
, &cur
->entry
);
2378 LeaveCriticalSection(&cs_registered_ps
);
2383 struct thread_context
2385 IComThreadingInfo IComThreadingInfo_iface
;
2386 IContextCallback IContextCallback_iface
;
2387 IObjContext IObjContext_iface
;
2391 static inline struct thread_context
*impl_from_IComThreadingInfo(IComThreadingInfo
*iface
)
2393 return CONTAINING_RECORD(iface
, struct thread_context
, IComThreadingInfo_iface
);
2396 static inline struct thread_context
*impl_from_IContextCallback(IContextCallback
*iface
)
2398 return CONTAINING_RECORD(iface
, struct thread_context
, IContextCallback_iface
);
2401 static inline struct thread_context
*impl_from_IObjContext(IObjContext
*iface
)
2403 return CONTAINING_RECORD(iface
, struct thread_context
, IObjContext_iface
);
2406 static HRESULT WINAPI
thread_context_info_QueryInterface(IComThreadingInfo
*iface
, REFIID riid
, void **obj
)
2408 struct thread_context
*context
= impl_from_IComThreadingInfo(iface
);
2412 if (IsEqualIID(riid
, &IID_IComThreadingInfo
) ||
2413 IsEqualIID(riid
, &IID_IUnknown
))
2415 *obj
= &context
->IComThreadingInfo_iface
;
2417 else if (IsEqualIID(riid
, &IID_IContextCallback
))
2419 *obj
= &context
->IContextCallback_iface
;
2421 else if (IsEqualIID(riid
, &IID_IObjContext
))
2423 *obj
= &context
->IObjContext_iface
;
2428 IUnknown_AddRef((IUnknown
*)*obj
);
2432 FIXME("interface not implemented %s\n", debugstr_guid(riid
));
2433 return E_NOINTERFACE
;
2436 static ULONG WINAPI
thread_context_info_AddRef(IComThreadingInfo
*iface
)
2438 struct thread_context
*context
= impl_from_IComThreadingInfo(iface
);
2439 return InterlockedIncrement(&context
->refcount
);
2442 static ULONG WINAPI
thread_context_info_Release(IComThreadingInfo
*iface
)
2444 struct thread_context
*context
= impl_from_IComThreadingInfo(iface
);
2446 /* Context instance is initially created with CoGetContextToken() with refcount set to 0,
2447 releasing context while refcount is at 0 destroys it. */
2448 if (!context
->refcount
)
2454 return InterlockedDecrement(&context
->refcount
);
2457 static HRESULT WINAPI
thread_context_info_GetCurrentApartmentType(IComThreadingInfo
*iface
, APTTYPE
*apttype
)
2459 APTTYPEQUALIFIER qualifier
;
2461 TRACE("%p\n", apttype
);
2463 return CoGetApartmentType(apttype
, &qualifier
);
2466 static HRESULT WINAPI
thread_context_info_GetCurrentThreadType(IComThreadingInfo
*iface
, THDTYPE
*thdtype
)
2468 APTTYPEQUALIFIER qualifier
;
2472 hr
= CoGetApartmentType(&apttype
, &qualifier
);
2476 TRACE("%p\n", thdtype
);
2481 case APTTYPE_MAINSTA
:
2482 *thdtype
= THDTYPE_PROCESSMESSAGES
;
2485 *thdtype
= THDTYPE_BLOCKMESSAGES
;
2491 static HRESULT WINAPI
thread_context_info_GetCurrentLogicalThreadId(IComThreadingInfo
*iface
, GUID
*logical_thread_id
)
2493 TRACE("%p\n", logical_thread_id
);
2495 return CoGetCurrentLogicalThreadId(logical_thread_id
);
2498 static HRESULT WINAPI
thread_context_info_SetCurrentLogicalThreadId(IComThreadingInfo
*iface
, REFGUID logical_thread_id
)
2500 FIXME("%s stub\n", debugstr_guid(logical_thread_id
));
2505 static const IComThreadingInfoVtbl thread_context_info_vtbl
=
2507 thread_context_info_QueryInterface
,
2508 thread_context_info_AddRef
,
2509 thread_context_info_Release
,
2510 thread_context_info_GetCurrentApartmentType
,
2511 thread_context_info_GetCurrentThreadType
,
2512 thread_context_info_GetCurrentLogicalThreadId
,
2513 thread_context_info_SetCurrentLogicalThreadId
2516 static HRESULT WINAPI
thread_context_callback_QueryInterface(IContextCallback
*iface
, REFIID riid
, void **obj
)
2518 struct thread_context
*context
= impl_from_IContextCallback(iface
);
2519 return IComThreadingInfo_QueryInterface(&context
->IComThreadingInfo_iface
, riid
, obj
);
2522 static ULONG WINAPI
thread_context_callback_AddRef(IContextCallback
*iface
)
2524 struct thread_context
*context
= impl_from_IContextCallback(iface
);
2525 return IComThreadingInfo_AddRef(&context
->IComThreadingInfo_iface
);
2528 static ULONG WINAPI
thread_context_callback_Release(IContextCallback
*iface
)
2530 struct thread_context
*context
= impl_from_IContextCallback(iface
);
2531 return IComThreadingInfo_Release(&context
->IComThreadingInfo_iface
);
2534 static HRESULT WINAPI
thread_context_callback_ContextCallback(IContextCallback
*iface
,
2535 PFNCONTEXTCALL callback
, ComCallData
*param
, REFIID riid
, int method
, IUnknown
*punk
)
2537 FIXME("%p, %p, %p, %s, %d, %p\n", iface
, callback
, param
, debugstr_guid(riid
), method
, punk
);
2542 static const IContextCallbackVtbl thread_context_callback_vtbl
=
2544 thread_context_callback_QueryInterface
,
2545 thread_context_callback_AddRef
,
2546 thread_context_callback_Release
,
2547 thread_context_callback_ContextCallback
2550 static HRESULT WINAPI
thread_object_context_QueryInterface(IObjContext
*iface
, REFIID riid
, void **obj
)
2552 struct thread_context
*context
= impl_from_IObjContext(iface
);
2553 return IComThreadingInfo_QueryInterface(&context
->IComThreadingInfo_iface
, riid
, obj
);
2556 static ULONG WINAPI
thread_object_context_AddRef(IObjContext
*iface
)
2558 struct thread_context
*context
= impl_from_IObjContext(iface
);
2559 return IComThreadingInfo_AddRef(&context
->IComThreadingInfo_iface
);
2562 static ULONG WINAPI
thread_object_context_Release(IObjContext
*iface
)
2564 struct thread_context
*context
= impl_from_IObjContext(iface
);
2565 return IComThreadingInfo_Release(&context
->IComThreadingInfo_iface
);
2568 static HRESULT WINAPI
thread_object_context_SetProperty(IObjContext
*iface
, REFGUID propid
, CPFLAGS flags
, IUnknown
*punk
)
2570 FIXME("%p, %s, %lx, %p\n", iface
, debugstr_guid(propid
), flags
, punk
);
2575 static HRESULT WINAPI
thread_object_context_RemoveProperty(IObjContext
*iface
, REFGUID propid
)
2577 FIXME("%p, %s\n", iface
, debugstr_guid(propid
));
2582 static HRESULT WINAPI
thread_object_context_GetProperty(IObjContext
*iface
, REFGUID propid
, CPFLAGS
*flags
, IUnknown
**punk
)
2584 FIXME("%p, %s, %p, %p\n", iface
, debugstr_guid(propid
), flags
, punk
);
2589 static HRESULT WINAPI
thread_object_context_EnumContextProps(IObjContext
*iface
, IEnumContextProps
**props
)
2591 FIXME("%p, %p\n", iface
, props
);
2596 static void WINAPI
thread_object_context_Reserved1(IObjContext
*iface
)
2598 FIXME("%p\n", iface
);
2601 static void WINAPI
thread_object_context_Reserved2(IObjContext
*iface
)
2603 FIXME("%p\n", iface
);
2606 static void WINAPI
thread_object_context_Reserved3(IObjContext
*iface
)
2608 FIXME("%p\n", iface
);
2611 static void WINAPI
thread_object_context_Reserved4(IObjContext
*iface
)
2613 FIXME("%p\n", iface
);
2616 static void WINAPI
thread_object_context_Reserved5(IObjContext
*iface
)
2618 FIXME("%p\n", iface
);
2621 static void WINAPI
thread_object_context_Reserved6(IObjContext
*iface
)
2623 FIXME("%p\n", iface
);
2626 static void WINAPI
thread_object_context_Reserved7(IObjContext
*iface
)
2628 FIXME("%p\n", iface
);
2631 static const IObjContextVtbl thread_object_context_vtbl
=
2633 thread_object_context_QueryInterface
,
2634 thread_object_context_AddRef
,
2635 thread_object_context_Release
,
2636 thread_object_context_SetProperty
,
2637 thread_object_context_RemoveProperty
,
2638 thread_object_context_GetProperty
,
2639 thread_object_context_EnumContextProps
,
2640 thread_object_context_Reserved1
,
2641 thread_object_context_Reserved2
,
2642 thread_object_context_Reserved3
,
2643 thread_object_context_Reserved4
,
2644 thread_object_context_Reserved5
,
2645 thread_object_context_Reserved6
,
2646 thread_object_context_Reserved7
2649 /***********************************************************************
2650 * CoGetContextToken (combase.@)
2652 HRESULT WINAPI
CoGetContextToken(ULONG_PTR
*token
)
2654 struct tlsdata
*tlsdata
;
2657 TRACE("%p\n", token
);
2659 if (!InternalIsProcessInitialized())
2661 ERR("apartment not initialised\n");
2662 return CO_E_NOTINITIALIZED
;
2665 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
2671 if (!tlsdata
->context_token
)
2673 struct thread_context
*context
;
2675 context
= calloc(1, sizeof(*context
));
2677 return E_OUTOFMEMORY
;
2679 context
->IComThreadingInfo_iface
.lpVtbl
= &thread_context_info_vtbl
;
2680 context
->IContextCallback_iface
.lpVtbl
= &thread_context_callback_vtbl
;
2681 context
->IObjContext_iface
.lpVtbl
= &thread_object_context_vtbl
;
2682 /* Context token does not take a reference, it's always zero until the
2683 interface is explicitly requested with CoGetObjectContext(). */
2684 context
->refcount
= 0;
2686 tlsdata
->context_token
= &context
->IObjContext_iface
;
2689 *token
= (ULONG_PTR
)tlsdata
->context_token
;
2690 TRACE("context_token %p\n", tlsdata
->context_token
);
2695 /***********************************************************************
2696 * CoGetCurrentLogicalThreadId (combase.@)
2698 HRESULT WINAPI
CoGetCurrentLogicalThreadId(GUID
*id
)
2700 struct tlsdata
*tlsdata
;
2704 return E_INVALIDARG
;
2706 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
2709 if (IsEqualGUID(&tlsdata
->causality_id
, &GUID_NULL
))
2711 CoCreateGuid(&tlsdata
->causality_id
);
2712 tlsdata
->flags
|= OLETLS_UUIDINITIALIZED
;
2715 *id
= tlsdata
->causality_id
;
2720 /******************************************************************************
2721 * CoGetCurrentProcess (combase.@)
2723 DWORD WINAPI
CoGetCurrentProcess(void)
2725 struct tlsdata
*tlsdata
;
2727 if (FAILED(com_get_tlsdata(&tlsdata
)))
2730 if (!tlsdata
->thread_seqid
)
2731 rpcss_get_next_seqid(&tlsdata
->thread_seqid
);
2733 return tlsdata
->thread_seqid
;
2736 /***********************************************************************
2737 * CoFreeUnusedLibrariesEx (combase.@)
2739 void WINAPI DECLSPEC_HOTPATCH
CoFreeUnusedLibrariesEx(DWORD unload_delay
, DWORD reserved
)
2741 struct apartment
*apt
= com_get_current_apt();
2744 ERR("apartment not initialised\n");
2748 apartment_freeunusedlibraries(apt
, unload_delay
);
2752 * When locked, don't modify list (unless we add a new head), so that it's
2753 * safe to iterate it. Freeing of list entries is delayed and done on unlock.
2755 static inline void lock_init_spies(struct tlsdata
*tlsdata
)
2757 tlsdata
->spies_lock
++;
2760 static void unlock_init_spies(struct tlsdata
*tlsdata
)
2762 struct init_spy
*spy
, *next
;
2764 if (--tlsdata
->spies_lock
) return;
2766 LIST_FOR_EACH_ENTRY_SAFE(spy
, next
, &tlsdata
->spies
, struct init_spy
, entry
)
2768 if (spy
->spy
) continue;
2769 list_remove(&spy
->entry
);
2774 /******************************************************************************
2775 * CoInitializeWOW (combase.@)
2777 HRESULT WINAPI
CoInitializeWOW(DWORD arg1
, DWORD arg2
)
2779 FIXME("%#lx, %#lx\n", arg1
, arg2
);
2784 /******************************************************************************
2785 * CoInitializeEx (combase.@)
2787 HRESULT WINAPI DECLSPEC_HOTPATCH
CoInitializeEx(void *reserved
, DWORD model
)
2789 struct tlsdata
*tlsdata
;
2790 struct init_spy
*cursor
;
2793 TRACE("%p, %#lx\n", reserved
, model
);
2796 WARN("Unexpected reserved argument %p\n", reserved
);
2798 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
2801 if (InterlockedExchangeAdd(&com_lockcount
, 1) == 0)
2802 TRACE("Initializing the COM libraries\n");
2804 lock_init_spies(tlsdata
);
2805 LIST_FOR_EACH_ENTRY(cursor
, &tlsdata
->spies
, struct init_spy
, entry
)
2807 if (cursor
->spy
) IInitializeSpy_PreInitialize(cursor
->spy
, model
, tlsdata
->inits
);
2809 unlock_init_spies(tlsdata
);
2811 hr
= enter_apartment(tlsdata
, model
);
2813 lock_init_spies(tlsdata
);
2814 LIST_FOR_EACH_ENTRY(cursor
, &tlsdata
->spies
, struct init_spy
, entry
)
2816 if (cursor
->spy
) hr
= IInitializeSpy_PostInitialize(cursor
->spy
, hr
, model
, tlsdata
->inits
);
2818 unlock_init_spies(tlsdata
);
2823 /***********************************************************************
2824 * CoUninitialize (combase.@)
2826 void WINAPI DECLSPEC_HOTPATCH
CoUninitialize(void)
2828 struct tlsdata
*tlsdata
;
2829 struct init_spy
*cursor
, *next
;
2834 if (FAILED(com_get_tlsdata(&tlsdata
)))
2837 lock_init_spies(tlsdata
);
2838 LIST_FOR_EACH_ENTRY_SAFE(cursor
, next
, &tlsdata
->spies
, struct init_spy
, entry
)
2840 if (cursor
->spy
) IInitializeSpy_PreUninitialize(cursor
->spy
, tlsdata
->inits
);
2842 unlock_init_spies(tlsdata
);
2845 if (!tlsdata
->inits
)
2847 ERR("Mismatched CoUninitialize\n");
2849 lock_init_spies(tlsdata
);
2850 LIST_FOR_EACH_ENTRY_SAFE(cursor
, next
, &tlsdata
->spies
, struct init_spy
, entry
)
2852 if (cursor
->spy
) IInitializeSpy_PostUninitialize(cursor
->spy
, tlsdata
->inits
);
2854 unlock_init_spies(tlsdata
);
2859 leave_apartment(tlsdata
);
2862 * Decrease the reference count.
2863 * If we are back to 0 locks on the COM library, make sure we free
2864 * all the associated data structures.
2866 lockcount
= InterlockedExchangeAdd(&com_lockcount
, -1);
2869 TRACE("Releasing the COM libraries\n");
2871 com_revoke_all_ps_clsids();
2872 DestroyRunningObjectTable();
2874 else if (lockcount
< 1)
2876 ERR("Unbalanced lock count %ld\n", lockcount
);
2877 InterlockedExchangeAdd(&com_lockcount
, 1);
2880 lock_init_spies(tlsdata
);
2881 LIST_FOR_EACH_ENTRY(cursor
, &tlsdata
->spies
, struct init_spy
, entry
)
2883 if (cursor
->spy
) IInitializeSpy_PostUninitialize(cursor
->spy
, tlsdata
->inits
);
2885 unlock_init_spies(tlsdata
);
2888 /***********************************************************************
2889 * CoIncrementMTAUsage (combase.@)
2891 HRESULT WINAPI
CoIncrementMTAUsage(CO_MTA_USAGE_COOKIE
*cookie
)
2893 TRACE("%p\n", cookie
);
2895 return apartment_increment_mta_usage(cookie
);
2898 /***********************************************************************
2899 * CoDecrementMTAUsage (combase.@)
2901 HRESULT WINAPI
CoDecrementMTAUsage(CO_MTA_USAGE_COOKIE cookie
)
2903 TRACE("%p\n", cookie
);
2905 apartment_decrement_mta_usage(cookie
);
2909 /***********************************************************************
2910 * CoGetApartmentType (combase.@)
2912 HRESULT WINAPI
CoGetApartmentType(APTTYPE
*type
, APTTYPEQUALIFIER
*qualifier
)
2914 struct tlsdata
*tlsdata
;
2915 struct apartment
*apt
;
2918 TRACE("%p, %p\n", type
, qualifier
);
2920 if (!type
|| !qualifier
)
2921 return E_INVALIDARG
;
2923 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
2927 *type
= APTTYPE_CURRENT
;
2928 else if (tlsdata
->apt
->multi_threaded
)
2929 *type
= APTTYPE_MTA
;
2930 else if (tlsdata
->apt
->main
)
2931 *type
= APTTYPE_MAINSTA
;
2933 *type
= APTTYPE_STA
;
2935 *qualifier
= APTTYPEQUALIFIER_NONE
;
2937 if (!tlsdata
->apt
&& (apt
= apartment_get_mta()))
2939 apartment_release(apt
);
2940 *type
= APTTYPE_MTA
;
2941 *qualifier
= APTTYPEQUALIFIER_IMPLICIT_MTA
;
2945 return tlsdata
->apt
? S_OK
: CO_E_NOTINITIALIZED
;
2948 /******************************************************************************
2949 * CoRegisterClassObject (combase.@)
2951 * MSDN claims that multiple interface registrations are legal, but we
2952 * can't do that with our current implementation.
2954 HRESULT WINAPI
CoRegisterClassObject(REFCLSID rclsid
, IUnknown
*object
, DWORD clscontext
,
2955 DWORD flags
, DWORD
*cookie
)
2957 static LONG next_cookie
;
2959 struct registered_class
*newclass
;
2960 IUnknown
*found_object
;
2961 struct apartment
*apt
;
2964 TRACE("%s, %p, %#lx, %#lx, %p\n", debugstr_guid(rclsid
), object
, clscontext
, flags
, cookie
);
2966 if (!cookie
|| !object
)
2967 return E_INVALIDARG
;
2969 if (!(apt
= apartment_get_current_or_mta()))
2971 ERR("COM was not initialized\n");
2972 return CO_E_NOTINITIALIZED
;
2977 /* REGCLS_MULTIPLEUSE implies registering as inproc server. This is what
2978 * differentiates the flag from REGCLS_MULTI_SEPARATE. */
2979 if (flags
& REGCLS_MULTIPLEUSE
)
2980 clscontext
|= CLSCTX_INPROC_SERVER
;
2983 * First, check if the class is already registered.
2984 * If it is, this should cause an error.
2986 if ((found_object
= com_get_registered_class_object(apt
, rclsid
, clscontext
)))
2988 if (flags
& REGCLS_MULTIPLEUSE
)
2990 if (clscontext
& CLSCTX_LOCAL_SERVER
)
2991 hr
= CoLockObjectExternal(found_object
, TRUE
, FALSE
);
2992 IUnknown_Release(found_object
);
2993 apartment_release(apt
);
2997 IUnknown_Release(found_object
);
2998 ERR("object already registered for class %s\n", debugstr_guid(rclsid
));
2999 apartment_release(apt
);
3000 return CO_E_OBJISREG
;
3003 newclass
= calloc(1, sizeof(*newclass
));
3006 apartment_release(apt
);
3007 return E_OUTOFMEMORY
;
3010 newclass
->clsid
= *rclsid
;
3011 newclass
->apartment_id
= apt
->oxid
;
3012 newclass
->clscontext
= clscontext
;
3013 newclass
->flags
= flags
;
3015 if (!(newclass
->cookie
= InterlockedIncrement(&next_cookie
)))
3016 newclass
->cookie
= InterlockedIncrement(&next_cookie
);
3018 newclass
->object
= object
;
3019 IUnknown_AddRef(newclass
->object
);
3021 EnterCriticalSection(®istered_classes_cs
);
3022 list_add_tail(®istered_classes
, &newclass
->entry
);
3023 LeaveCriticalSection(®istered_classes_cs
);
3025 *cookie
= newclass
->cookie
;
3027 if (clscontext
& CLSCTX_LOCAL_SERVER
)
3029 IStream
*marshal_stream
;
3031 hr
= apartment_get_local_server_stream(apt
, &marshal_stream
);
3034 apartment_release(apt
);
3038 hr
= rpc_register_local_server(&newclass
->clsid
, marshal_stream
, flags
, &newclass
->rpcss_cookie
);
3039 IStream_Release(marshal_stream
);
3042 apartment_release(apt
);
3046 static void com_revoke_class_object(struct registered_class
*entry
)
3048 list_remove(&entry
->entry
);
3050 if (entry
->clscontext
& CLSCTX_LOCAL_SERVER
)
3051 rpc_revoke_local_server(entry
->rpcss_cookie
);
3053 IUnknown_Release(entry
->object
);
3057 /* Cleans up rpcss registry */
3058 static void com_revoke_local_servers(void)
3060 struct registered_class
*cur
, *cur2
;
3062 EnterCriticalSection(®istered_classes_cs
);
3064 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, ®istered_classes
, struct registered_class
, entry
)
3066 if (cur
->clscontext
& CLSCTX_LOCAL_SERVER
)
3067 com_revoke_class_object(cur
);
3070 LeaveCriticalSection(®istered_classes_cs
);
3073 void apartment_revoke_all_classes(const struct apartment
*apt
)
3075 struct registered_class
*cur
, *cur2
;
3077 EnterCriticalSection(®istered_classes_cs
);
3079 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, ®istered_classes
, struct registered_class
, entry
)
3081 if (cur
->apartment_id
== apt
->oxid
)
3082 com_revoke_class_object(cur
);
3085 LeaveCriticalSection(®istered_classes_cs
);
3088 /***********************************************************************
3089 * CoRevokeClassObject (combase.@)
3091 HRESULT WINAPI DECLSPEC_HOTPATCH
CoRevokeClassObject(DWORD cookie
)
3093 HRESULT hr
= E_INVALIDARG
;
3094 struct registered_class
*cur
;
3095 struct apartment
*apt
;
3097 TRACE("%#lx\n", cookie
);
3099 if (!(apt
= apartment_get_current_or_mta()))
3101 ERR("COM was not initialized\n");
3102 return CO_E_NOTINITIALIZED
;
3105 EnterCriticalSection(®istered_classes_cs
);
3107 LIST_FOR_EACH_ENTRY(cur
, ®istered_classes
, struct registered_class
, entry
)
3109 if (cur
->cookie
!= cookie
)
3112 if (cur
->apartment_id
== apt
->oxid
)
3114 com_revoke_class_object(cur
);
3119 ERR("called from wrong apartment, should be called from %s\n", wine_dbgstr_longlong(cur
->apartment_id
));
3120 hr
= RPC_E_WRONG_THREAD
;
3126 LeaveCriticalSection(®istered_classes_cs
);
3127 apartment_release(apt
);
3132 /***********************************************************************
3133 * CoAddRefServerProcess (combase.@)
3135 ULONG WINAPI
CoAddRefServerProcess(void)
3141 EnterCriticalSection(®istered_classes_cs
);
3142 refs
= ++com_server_process_refcount
;
3143 LeaveCriticalSection(®istered_classes_cs
);
3145 TRACE("refs before: %ld\n", refs
- 1);
3150 /***********************************************************************
3151 * CoReleaseServerProcess [OLE32.@]
3153 ULONG WINAPI
CoReleaseServerProcess(void)
3159 EnterCriticalSection(®istered_classes_cs
);
3161 refs
= --com_server_process_refcount
;
3162 /* FIXME: suspend objects */
3164 LeaveCriticalSection(®istered_classes_cs
);
3166 TRACE("refs after: %ld\n", refs
);
3171 /******************************************************************************
3172 * CoDisconnectObject (combase.@)
3174 HRESULT WINAPI
CoDisconnectObject(IUnknown
*object
, DWORD reserved
)
3176 struct stub_manager
*manager
;
3177 struct apartment
*apt
;
3181 TRACE("%p, %#lx\n", object
, reserved
);
3184 return E_INVALIDARG
;
3186 hr
= IUnknown_QueryInterface(object
, &IID_IMarshal
, (void **)&marshal
);
3189 hr
= IMarshal_DisconnectObject(marshal
, reserved
);
3190 IMarshal_Release(marshal
);
3194 if (!(apt
= apartment_get_current_or_mta()))
3196 ERR("apartment not initialised\n");
3197 return CO_E_NOTINITIALIZED
;
3200 manager
= get_stub_manager_from_object(apt
, object
, FALSE
);
3203 stub_manager_disconnect(manager
);
3204 /* Release stub manager twice, to remove the apartment reference. */
3205 stub_manager_int_release(manager
);
3206 stub_manager_int_release(manager
);
3209 /* Note: native is pretty broken here because it just silently
3210 * fails, without returning an appropriate error code if the object was
3211 * not found, making apps think that the object was disconnected, when
3212 * it actually wasn't */
3214 apartment_release(apt
);
3218 /******************************************************************************
3219 * CoLockObjectExternal (combase.@)
3221 HRESULT WINAPI
CoLockObjectExternal(IUnknown
*object
, BOOL lock
, BOOL last_unlock_releases
)
3223 struct stub_manager
*stubmgr
;
3224 struct apartment
*apt
;
3226 TRACE("%p, %d, %d\n", object
, lock
, last_unlock_releases
);
3228 if (!(apt
= apartment_get_current_or_mta()))
3230 ERR("apartment not initialised\n");
3231 return CO_E_NOTINITIALIZED
;
3234 stubmgr
= get_stub_manager_from_object(apt
, object
, lock
);
3237 WARN("stub object not found %p\n", object
);
3238 /* Note: native is pretty broken here because it just silently
3239 * fails, without returning an appropriate error code, making apps
3240 * think that the object was disconnected, when it actually wasn't */
3241 apartment_release(apt
);
3246 stub_manager_ext_addref(stubmgr
, 1, FALSE
);
3248 stub_manager_ext_release(stubmgr
, 1, FALSE
, last_unlock_releases
);
3250 stub_manager_int_release(stubmgr
);
3251 apartment_release(apt
);
3255 /***********************************************************************
3256 * CoRegisterChannelHook (combase.@)
3258 HRESULT WINAPI
CoRegisterChannelHook(REFGUID guidExtension
, IChannelHook
*channel_hook
)
3260 TRACE("%s, %p\n", debugstr_guid(guidExtension
), channel_hook
);
3262 return rpc_register_channel_hook(guidExtension
, channel_hook
);
3265 /***********************************************************************
3266 * CoDisableCallCancellation (combase.@)
3268 HRESULT WINAPI
CoDisableCallCancellation(void *reserved
)
3270 struct tlsdata
*tlsdata
;
3273 TRACE("%p\n", reserved
);
3275 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
3278 if (!tlsdata
->cancelcount
)
3279 return CO_E_CANCEL_DISABLED
;
3281 tlsdata
->cancelcount
--;
3286 /***********************************************************************
3287 * CoEnableCallCancellation (combase.@)
3289 HRESULT WINAPI
CoEnableCallCancellation(void *reserved
)
3291 struct tlsdata
*tlsdata
;
3294 TRACE("%p\n", reserved
);
3296 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
3299 tlsdata
->cancelcount
++;
3304 /***********************************************************************
3305 * CoGetCallerTID (combase.@)
3307 HRESULT WINAPI
CoGetCallerTID(DWORD
*tid
)
3313 /***********************************************************************
3314 * CoIsHandlerConnected (combase.@)
3316 BOOL WINAPI
CoIsHandlerConnected(IUnknown
*object
)
3318 FIXME("%p\n", object
);
3323 /***********************************************************************
3324 * CoSuspendClassObjects (combase.@)
3326 HRESULT WINAPI
CoSuspendClassObjects(void)
3333 /***********************************************************************
3334 * CoResumeClassObjects (combase.@)
3336 HRESULT WINAPI
CoResumeClassObjects(void)
3343 /***********************************************************************
3344 * CoRegisterSurrogate (combase.@)
3346 HRESULT WINAPI
CoRegisterSurrogate(ISurrogate
*surrogate
)
3348 FIXME("%p stub\n", surrogate
);
3353 /***********************************************************************
3354 * CoRegisterSurrogateEx (combase.@)
3356 HRESULT WINAPI
CoRegisterSurrogateEx(REFGUID guid
, void *reserved
)
3358 FIXME("%s, %p stub\n", debugstr_guid(guid
), reserved
);
3363 /***********************************************************************
3364 * DllMain (combase.@)
3366 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD reason
, LPVOID reserved
)
3368 TRACE("%p, %#lx, %p\n", hinstDLL
, reason
, reserved
);
3372 case DLL_PROCESS_ATTACH
:
3373 hProxyDll
= hinstDLL
;
3375 case DLL_PROCESS_DETACH
:
3376 com_revoke_local_servers();
3377 if (reserved
) break;
3378 apartment_global_cleanup();
3379 DeleteCriticalSection(®istered_classes_cs
);
3380 rpc_unregister_channel_hooks();
3382 case DLL_THREAD_DETACH
:
3383 com_cleanup_tlsdata();
3390 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, void **obj
)
3392 TRACE("%s, %s, %p.\n", debugstr_guid(rclsid
), debugstr_guid(riid
), obj
);
3396 if (IsEqualCLSID(rclsid
, &CLSID_GlobalOptions
))
3397 return IClassFactory_QueryInterface(&global_options_factory
, riid
, obj
);
3399 return CLASS_E_CLASSNOTAVAILABLE
;