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
21 #define NONAMELESSUNION
24 #define WIN32_NO_STATUS
25 #define USE_COM_CONTEXT_DEF
32 #include "combase_private.h"
34 #include "wine/debug.h"
35 #include "wine/heap.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
42 extern void WINAPI
DestroyRunningObjectTable(void);
43 extern HRESULT WINAPI
Ole32DllGetClassObject(REFCLSID rclsid
, REFIID riid
, void **obj
);
46 * Number of times CoInitialize is called. It is decreased every time CoUninitialize is called. When it hits 0, the COM libraries are freed
48 static LONG com_lockcount
;
50 static LONG com_server_process_refcount
;
52 struct comclassredirect_data
68 DWORD miscstatuscontent
;
69 DWORD miscstatusthumbnail
;
71 DWORD miscstatusdocprint
;
74 struct ifacepsredirect_data
86 struct progidredirect_data
107 static struct list registered_proxystubs
= LIST_INIT(registered_proxystubs
);
109 static CRITICAL_SECTION cs_registered_ps
;
110 static CRITICAL_SECTION_DEBUG psclsid_cs_debug
=
112 0, 0, &cs_registered_ps
,
113 { &psclsid_cs_debug
.ProcessLocksList
, &psclsid_cs_debug
.ProcessLocksList
},
114 0, 0, { (DWORD_PTR
)(__FILE__
": cs_registered_psclsid_list") }
116 static CRITICAL_SECTION cs_registered_ps
= { &psclsid_cs_debug
, -1, 0, 0, 0, 0 };
118 struct registered_class
127 unsigned int rpcss_cookie
;
130 static struct list registered_classes
= LIST_INIT(registered_classes
);
132 static CRITICAL_SECTION registered_classes_cs
;
133 static CRITICAL_SECTION_DEBUG registered_classes_cs_debug
=
135 0, 0, ®istered_classes_cs
,
136 { ®istered_classes_cs_debug
.ProcessLocksList
, ®istered_classes_cs_debug
.ProcessLocksList
},
137 0, 0, { (DWORD_PTR
)(__FILE__
": registered_classes_cs") }
139 static CRITICAL_SECTION registered_classes_cs
= { ®istered_classes_cs_debug
, -1, 0, 0, 0, 0 };
141 IUnknown
* com_get_registered_class_object(const struct apartment
*apt
, REFCLSID rclsid
, DWORD clscontext
)
143 struct registered_class
*cur
;
144 IUnknown
*object
= NULL
;
146 EnterCriticalSection(®istered_classes_cs
);
148 LIST_FOR_EACH_ENTRY(cur
, ®istered_classes
, struct registered_class
, entry
)
150 if ((apt
->oxid
== cur
->apartment_id
) &&
151 (clscontext
& cur
->clscontext
) &&
152 IsEqualGUID(&cur
->clsid
, rclsid
))
154 object
= cur
->object
;
155 IUnknown_AddRef(cur
->object
);
160 LeaveCriticalSection(®istered_classes_cs
);
165 static struct init_spy
*get_spy_entry(struct tlsdata
*tlsdata
, unsigned int id
)
167 struct init_spy
*spy
;
169 LIST_FOR_EACH_ENTRY(spy
, &tlsdata
->spies
, struct init_spy
, entry
)
171 if (id
== spy
->id
&& spy
->spy
)
178 static NTSTATUS
create_key(HKEY
*retkey
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
)
180 NTSTATUS status
= NtCreateKey((HANDLE
*)retkey
, access
, attr
, 0, NULL
, 0, NULL
);
182 if (status
== STATUS_OBJECT_NAME_NOT_FOUND
)
184 HANDLE subkey
, root
= attr
->RootDirectory
;
185 WCHAR
*buffer
= attr
->ObjectName
->Buffer
;
186 DWORD attrs
, pos
= 0, i
= 0, len
= attr
->ObjectName
->Length
/ sizeof(WCHAR
);
189 while (i
< len
&& buffer
[i
] != '\\') i
++;
190 if (i
== len
) return status
;
192 attrs
= attr
->Attributes
;
193 attr
->ObjectName
= &str
;
197 str
.Buffer
= buffer
+ pos
;
198 str
.Length
= (i
- pos
) * sizeof(WCHAR
);
199 status
= NtCreateKey(&subkey
, access
, attr
, 0, NULL
, 0, NULL
);
200 if (attr
->RootDirectory
!= root
) NtClose(attr
->RootDirectory
);
201 if (status
) return status
;
202 attr
->RootDirectory
= subkey
;
203 while (i
< len
&& buffer
[i
] == '\\') i
++;
205 while (i
< len
&& buffer
[i
] != '\\') i
++;
207 str
.Buffer
= buffer
+ pos
;
208 str
.Length
= (i
- pos
) * sizeof(WCHAR
);
209 attr
->Attributes
= attrs
;
210 status
= NtCreateKey((HANDLE
*)retkey
, access
, attr
, 0, NULL
, 0, NULL
);
211 if (attr
->RootDirectory
!= root
) NtClose(attr
->RootDirectory
);
216 static HKEY classes_root_hkey
;
218 static HKEY
create_classes_root_hkey(DWORD access
)
221 OBJECT_ATTRIBUTES attr
;
224 attr
.Length
= sizeof(attr
);
225 attr
.RootDirectory
= 0;
226 attr
.ObjectName
= &name
;
228 attr
.SecurityDescriptor
= NULL
;
229 attr
.SecurityQualityOfService
= NULL
;
230 RtlInitUnicodeString(&name
, L
"\\Registry\\Machine\\Software\\Classes");
232 if (create_key( &hkey
, access
, &attr
)) return 0;
233 TRACE( "%s -> %p\n", debugstr_w(attr
.ObjectName
->Buffer
), hkey
);
235 if (!(access
& KEY_WOW64_64KEY
))
237 if (!(ret
= InterlockedCompareExchangePointer( (void **)&classes_root_hkey
, hkey
, 0 )))
240 NtClose( hkey
); /* somebody beat us to it */
247 static HKEY
get_classes_root_hkey(HKEY hkey
, REGSAM access
);
249 static LSTATUS
create_classes_key(HKEY hkey
, const WCHAR
*name
, REGSAM access
, HKEY
*retkey
)
251 OBJECT_ATTRIBUTES attr
;
252 UNICODE_STRING nameW
;
254 if (!(hkey
= get_classes_root_hkey(hkey
, access
)))
255 return ERROR_INVALID_HANDLE
;
257 attr
.Length
= sizeof(attr
);
258 attr
.RootDirectory
= hkey
;
259 attr
.ObjectName
= &nameW
;
261 attr
.SecurityDescriptor
= NULL
;
262 attr
.SecurityQualityOfService
= NULL
;
263 RtlInitUnicodeString( &nameW
, name
);
265 return RtlNtStatusToDosError(create_key(retkey
, access
, &attr
));
268 static HKEY
get_classes_root_hkey(HKEY hkey
, REGSAM access
)
271 const BOOL is_win64
= sizeof(void*) > sizeof(int);
272 const BOOL force_wow32
= is_win64
&& (access
& KEY_WOW64_32KEY
);
274 if (hkey
== HKEY_CLASSES_ROOT
&&
275 ((access
& KEY_WOW64_64KEY
) || !(ret
= classes_root_hkey
)))
276 ret
= create_classes_root_hkey(MAXIMUM_ALLOWED
| (access
& KEY_WOW64_64KEY
));
277 if (force_wow32
&& ret
&& ret
== classes_root_hkey
)
279 access
&= ~KEY_WOW64_32KEY
;
280 if (create_classes_key(classes_root_hkey
, L
"Wow6432Node", access
, &hkey
))
288 static LSTATUS
open_classes_key(HKEY hkey
, const WCHAR
*name
, REGSAM access
, HKEY
*retkey
)
290 OBJECT_ATTRIBUTES attr
;
291 UNICODE_STRING nameW
;
293 if (!(hkey
= get_classes_root_hkey(hkey
, access
)))
294 return ERROR_INVALID_HANDLE
;
296 attr
.Length
= sizeof(attr
);
297 attr
.RootDirectory
= hkey
;
298 attr
.ObjectName
= &nameW
;
300 attr
.SecurityDescriptor
= NULL
;
301 attr
.SecurityQualityOfService
= NULL
;
302 RtlInitUnicodeString( &nameW
, name
);
304 return RtlNtStatusToDosError(NtOpenKey((HANDLE
*)retkey
, access
, &attr
));
307 HRESULT
open_key_for_clsid(REFCLSID clsid
, const WCHAR
*keyname
, REGSAM access
, HKEY
*subkey
)
309 static const WCHAR clsidW
[] = L
"CLSID\\";
310 WCHAR path
[CHARS_IN_GUID
+ ARRAY_SIZE(clsidW
) - 1];
314 lstrcpyW(path
, clsidW
);
315 StringFromGUID2(clsid
, path
+ lstrlenW(clsidW
), CHARS_IN_GUID
);
316 res
= open_classes_key(HKEY_CLASSES_ROOT
, path
, keyname
? KEY_READ
: access
, &key
);
317 if (res
== ERROR_FILE_NOT_FOUND
)
318 return REGDB_E_CLASSNOTREG
;
319 else if (res
!= ERROR_SUCCESS
)
320 return REGDB_E_READREGDB
;
328 res
= open_classes_key(key
, keyname
, access
, subkey
);
330 if (res
== ERROR_FILE_NOT_FOUND
)
331 return REGDB_E_KEYMISSING
;
332 else if (res
!= ERROR_SUCCESS
)
333 return REGDB_E_READREGDB
;
338 /* open HKCR\\AppId\\{string form of appid clsid} key */
339 HRESULT
open_appidkey_from_clsid(REFCLSID clsid
, REGSAM access
, HKEY
*subkey
)
341 static const WCHAR appidkeyW
[] = L
"AppId\\";
343 WCHAR buf
[CHARS_IN_GUID
];
344 WCHAR keyname
[ARRAY_SIZE(appidkeyW
) + CHARS_IN_GUID
];
350 /* read the AppID value under the class's key */
351 hr
= open_key_for_clsid(clsid
, NULL
, KEY_READ
, &hkey
);
356 res
= RegQueryValueExW(hkey
, L
"AppId", NULL
, &type
, (LPBYTE
)buf
, &size
);
358 if (res
== ERROR_FILE_NOT_FOUND
)
359 return REGDB_E_KEYMISSING
;
360 else if (res
!= ERROR_SUCCESS
|| type
!=REG_SZ
)
361 return REGDB_E_READREGDB
;
363 lstrcpyW(keyname
, appidkeyW
);
364 lstrcatW(keyname
, buf
);
365 res
= open_classes_key(HKEY_CLASSES_ROOT
, keyname
, access
, subkey
);
366 if (res
== ERROR_FILE_NOT_FOUND
)
367 return REGDB_E_KEYMISSING
;
368 else if (res
!= ERROR_SUCCESS
)
369 return REGDB_E_READREGDB
;
374 /***********************************************************************
375 * InternalIsProcessInitialized (combase.@)
377 BOOL WINAPI
InternalIsProcessInitialized(void)
379 struct apartment
*apt
;
381 if (!(apt
= apartment_get_current_or_mta()))
383 apartment_release(apt
);
388 /***********************************************************************
389 * InternalTlsAllocData (combase.@)
391 HRESULT WINAPI
InternalTlsAllocData(struct tlsdata
**data
)
393 if (!(*data
= heap_alloc_zero(sizeof(**data
))))
394 return E_OUTOFMEMORY
;
396 list_init(&(*data
)->spies
);
397 NtCurrentTeb()->ReservedForOle
= *data
;
402 static void com_cleanup_tlsdata(void)
404 struct tlsdata
*tlsdata
= NtCurrentTeb()->ReservedForOle
;
405 struct init_spy
*cursor
, *cursor2
;
411 apartment_release(tlsdata
->apt
);
412 if (tlsdata
->errorinfo
)
413 IErrorInfo_Release(tlsdata
->errorinfo
);
415 IUnknown_Release(tlsdata
->state
);
417 LIST_FOR_EACH_ENTRY_SAFE(cursor
, cursor2
, &tlsdata
->spies
, struct init_spy
, entry
)
419 list_remove(&cursor
->entry
);
421 IInitializeSpy_Release(cursor
->spy
);
425 if (tlsdata
->context_token
)
426 IObjContext_Release(tlsdata
->context_token
);
429 NtCurrentTeb()->ReservedForOle
= NULL
;
432 /***********************************************************************
433 * FreePropVariantArray (combase.@)
435 HRESULT WINAPI
FreePropVariantArray(ULONG count
, PROPVARIANT
*rgvars
)
439 TRACE("%u, %p.\n", count
, rgvars
);
444 for (i
= 0; i
< count
; ++i
)
445 PropVariantClear(&rgvars
[i
]);
450 static HRESULT
propvar_validatetype(VARTYPE vt
)
482 case VT_STREAMED_OBJECT
:
483 case VT_STORED_OBJECT
:
487 case VT_I1
|VT_VECTOR
:
488 case VT_I2
|VT_VECTOR
:
489 case VT_I4
|VT_VECTOR
:
490 case VT_I8
|VT_VECTOR
:
491 case VT_R4
|VT_VECTOR
:
492 case VT_R8
|VT_VECTOR
:
493 case VT_CY
|VT_VECTOR
:
494 case VT_DATE
|VT_VECTOR
:
495 case VT_BSTR
|VT_VECTOR
:
496 case VT_ERROR
|VT_VECTOR
:
497 case VT_BOOL
|VT_VECTOR
:
498 case VT_VARIANT
|VT_VECTOR
:
499 case VT_UI1
|VT_VECTOR
:
500 case VT_UI2
|VT_VECTOR
:
501 case VT_UI4
|VT_VECTOR
:
502 case VT_UI8
|VT_VECTOR
:
503 case VT_LPSTR
|VT_VECTOR
:
504 case VT_LPWSTR
|VT_VECTOR
:
505 case VT_FILETIME
|VT_VECTOR
:
506 case VT_CF
|VT_VECTOR
:
507 case VT_CLSID
|VT_VECTOR
:
509 case VT_ARRAY
|VT_UI1
:
511 case VT_ARRAY
|VT_UI2
:
513 case VT_ARRAY
|VT_UI4
:
514 case VT_ARRAY
|VT_INT
:
515 case VT_ARRAY
|VT_UINT
:
519 case VT_ARRAY
|VT_DATE
:
520 case VT_ARRAY
|VT_BSTR
:
521 case VT_ARRAY
|VT_BOOL
:
522 case VT_ARRAY
|VT_DECIMAL
:
523 case VT_ARRAY
|VT_DISPATCH
:
524 case VT_ARRAY
|VT_UNKNOWN
:
525 case VT_ARRAY
|VT_ERROR
:
526 case VT_ARRAY
|VT_VARIANT
:
529 WARN("Bad type %d\n", vt
);
530 return STG_E_INVALIDPARAMETER
;
533 static void propvar_free_cf_array(ULONG count
, CLIPDATA
*data
)
536 for (i
= 0; i
< count
; ++i
)
537 CoTaskMemFree(data
[i
].pClipData
);
540 /***********************************************************************
541 * PropVariantClear (combase.@)
543 HRESULT WINAPI
PropVariantClear(PROPVARIANT
*pvar
)
547 TRACE("%p.\n", pvar
);
552 hr
= propvar_validatetype(pvar
->vt
);
555 memset(pvar
, 0, sizeof(*pvar
));
585 case VT_STREAMED_OBJECT
:
587 case VT_STORED_OBJECT
:
589 IStream_Release(pvar
->u
.pStream
);
594 /* pick an arbitrary typed pointer - we don't care about the type
595 * as we are just freeing it */
596 CoTaskMemFree(pvar
->u
.puuid
);
600 CoTaskMemFree(pvar
->u
.blob
.pBlobData
);
603 SysFreeString(pvar
->u
.bstrVal
);
606 if (pvar
->u
.pclipdata
)
608 propvar_free_cf_array(1, pvar
->u
.pclipdata
);
609 CoTaskMemFree(pvar
->u
.pclipdata
);
613 if (pvar
->vt
& VT_VECTOR
)
617 switch (pvar
->vt
& ~VT_VECTOR
)
620 FreePropVariantArray(pvar
->u
.capropvar
.cElems
, pvar
->u
.capropvar
.pElems
);
623 propvar_free_cf_array(pvar
->u
.caclipdata
.cElems
, pvar
->u
.caclipdata
.pElems
);
626 for (i
= 0; i
< pvar
->u
.cabstr
.cElems
; i
++)
627 SysFreeString(pvar
->u
.cabstr
.pElems
[i
]);
630 for (i
= 0; i
< pvar
->u
.calpstr
.cElems
; i
++)
631 CoTaskMemFree(pvar
->u
.calpstr
.pElems
[i
]);
634 for (i
= 0; i
< pvar
->u
.calpwstr
.cElems
; i
++)
635 CoTaskMemFree(pvar
->u
.calpwstr
.pElems
[i
]);
638 if (pvar
->vt
& ~VT_VECTOR
)
640 /* pick an arbitrary VT_VECTOR structure - they all have the same
642 CoTaskMemFree(pvar
->u
.capropvar
.pElems
);
645 else if (pvar
->vt
& VT_ARRAY
)
646 hr
= SafeArrayDestroy(pvar
->u
.parray
);
649 WARN("Invalid/unsupported type %d\n", pvar
->vt
);
650 hr
= STG_E_INVALIDPARAMETER
;
654 memset(pvar
, 0, sizeof(*pvar
));
658 /***********************************************************************
659 * PropVariantCopy (combase.@)
661 HRESULT WINAPI
PropVariantCopy(PROPVARIANT
*pvarDest
, const PROPVARIANT
*pvarSrc
)
666 TRACE("%p, %p vt %04x.\n", pvarDest
, pvarSrc
, pvarSrc
->vt
);
668 hr
= propvar_validatetype(pvarSrc
->vt
);
670 return DISP_E_BADVARTYPE
;
672 /* this will deal with most cases */
673 *pvarDest
= *pvarSrc
;
701 case VT_STREAMED_OBJECT
:
703 case VT_STORED_OBJECT
:
704 if (pvarDest
->u
.pStream
)
705 IStream_AddRef(pvarDest
->u
.pStream
);
708 pvarDest
->u
.puuid
= CoTaskMemAlloc(sizeof(CLSID
));
709 *pvarDest
->u
.puuid
= *pvarSrc
->u
.puuid
;
712 if (pvarSrc
->u
.pszVal
)
714 len
= strlen(pvarSrc
->u
.pszVal
);
715 pvarDest
->u
.pszVal
= CoTaskMemAlloc((len
+1)*sizeof(CHAR
));
716 CopyMemory(pvarDest
->u
.pszVal
, pvarSrc
->u
.pszVal
, (len
+1)*sizeof(CHAR
));
720 if (pvarSrc
->u
.pwszVal
)
722 len
= lstrlenW(pvarSrc
->u
.pwszVal
);
723 pvarDest
->u
.pwszVal
= CoTaskMemAlloc((len
+1)*sizeof(WCHAR
));
724 CopyMemory(pvarDest
->u
.pwszVal
, pvarSrc
->u
.pwszVal
, (len
+1)*sizeof(WCHAR
));
729 if (pvarSrc
->u
.blob
.pBlobData
)
731 len
= pvarSrc
->u
.blob
.cbSize
;
732 pvarDest
->u
.blob
.pBlobData
= CoTaskMemAlloc(len
);
733 CopyMemory(pvarDest
->u
.blob
.pBlobData
, pvarSrc
->u
.blob
.pBlobData
, len
);
737 pvarDest
->u
.bstrVal
= SysAllocString(pvarSrc
->u
.bstrVal
);
740 if (pvarSrc
->u
.pclipdata
)
742 len
= pvarSrc
->u
.pclipdata
->cbSize
- sizeof(pvarSrc
->u
.pclipdata
->ulClipFmt
);
743 pvarDest
->u
.pclipdata
= CoTaskMemAlloc(sizeof (CLIPDATA
));
744 pvarDest
->u
.pclipdata
->cbSize
= pvarSrc
->u
.pclipdata
->cbSize
;
745 pvarDest
->u
.pclipdata
->ulClipFmt
= pvarSrc
->u
.pclipdata
->ulClipFmt
;
746 pvarDest
->u
.pclipdata
->pClipData
= CoTaskMemAlloc(len
);
747 CopyMemory(pvarDest
->u
.pclipdata
->pClipData
, pvarSrc
->u
.pclipdata
->pClipData
, len
);
751 if (pvarSrc
->vt
& VT_VECTOR
)
756 switch (pvarSrc
->vt
& ~VT_VECTOR
)
758 case VT_I1
: elemSize
= sizeof(pvarSrc
->u
.cVal
); break;
759 case VT_UI1
: elemSize
= sizeof(pvarSrc
->u
.bVal
); break;
760 case VT_I2
: elemSize
= sizeof(pvarSrc
->u
.iVal
); break;
761 case VT_UI2
: elemSize
= sizeof(pvarSrc
->u
.uiVal
); break;
762 case VT_BOOL
: elemSize
= sizeof(pvarSrc
->u
.boolVal
); break;
763 case VT_I4
: elemSize
= sizeof(pvarSrc
->u
.lVal
); break;
764 case VT_UI4
: elemSize
= sizeof(pvarSrc
->u
.ulVal
); break;
765 case VT_R4
: elemSize
= sizeof(pvarSrc
->u
.fltVal
); break;
766 case VT_R8
: elemSize
= sizeof(pvarSrc
->u
.dblVal
); break;
767 case VT_ERROR
: elemSize
= sizeof(pvarSrc
->u
.scode
); break;
768 case VT_I8
: elemSize
= sizeof(pvarSrc
->u
.hVal
); break;
769 case VT_UI8
: elemSize
= sizeof(pvarSrc
->u
.uhVal
); break;
770 case VT_CY
: elemSize
= sizeof(pvarSrc
->u
.cyVal
); break;
771 case VT_DATE
: elemSize
= sizeof(pvarSrc
->u
.date
); break;
772 case VT_FILETIME
: elemSize
= sizeof(pvarSrc
->u
.filetime
); break;
773 case VT_CLSID
: elemSize
= sizeof(*pvarSrc
->u
.puuid
); break;
774 case VT_CF
: elemSize
= sizeof(*pvarSrc
->u
.pclipdata
); break;
775 case VT_BSTR
: elemSize
= sizeof(pvarSrc
->u
.bstrVal
); break;
776 case VT_LPSTR
: elemSize
= sizeof(pvarSrc
->u
.pszVal
); break;
777 case VT_LPWSTR
: elemSize
= sizeof(pvarSrc
->u
.pwszVal
); break;
778 case VT_VARIANT
: elemSize
= sizeof(*pvarSrc
->u
.pvarVal
); break;
781 FIXME("Invalid element type: %ul\n", pvarSrc
->vt
& ~VT_VECTOR
);
784 len
= pvarSrc
->u
.capropvar
.cElems
;
785 pvarDest
->u
.capropvar
.pElems
= len
? CoTaskMemAlloc(len
* elemSize
) : NULL
;
786 if (pvarSrc
->vt
== (VT_VECTOR
| VT_VARIANT
))
788 for (i
= 0; i
< len
; i
++)
789 PropVariantCopy(&pvarDest
->u
.capropvar
.pElems
[i
], &pvarSrc
->u
.capropvar
.pElems
[i
]);
791 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_CF
))
793 FIXME("Copy clipformats\n");
795 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_BSTR
))
797 for (i
= 0; i
< len
; i
++)
798 pvarDest
->u
.cabstr
.pElems
[i
] = SysAllocString(pvarSrc
->u
.cabstr
.pElems
[i
]);
800 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_LPSTR
))
803 for (i
= 0; i
< len
; i
++)
805 strLen
= lstrlenA(pvarSrc
->u
.calpstr
.pElems
[i
]) + 1;
806 pvarDest
->u
.calpstr
.pElems
[i
] = CoTaskMemAlloc(strLen
);
807 memcpy(pvarDest
->u
.calpstr
.pElems
[i
],
808 pvarSrc
->u
.calpstr
.pElems
[i
], strLen
);
811 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_LPWSTR
))
814 for (i
= 0; i
< len
; i
++)
816 strLen
= (lstrlenW(pvarSrc
->u
.calpwstr
.pElems
[i
]) + 1) *
818 pvarDest
->u
.calpstr
.pElems
[i
] = CoTaskMemAlloc(strLen
);
819 memcpy(pvarDest
->u
.calpstr
.pElems
[i
],
820 pvarSrc
->u
.calpstr
.pElems
[i
], strLen
);
824 CopyMemory(pvarDest
->u
.capropvar
.pElems
, pvarSrc
->u
.capropvar
.pElems
, len
* elemSize
);
826 else if (pvarSrc
->vt
& VT_ARRAY
)
828 pvarDest
->u
.uhVal
.QuadPart
= 0;
829 return SafeArrayCopy(pvarSrc
->u
.parray
, &pvarDest
->u
.parray
);
832 WARN("Invalid/unsupported type %d\n", pvarSrc
->vt
);
838 /***********************************************************************
839 * CoFileTimeNow (combase.@)
841 HRESULT WINAPI
CoFileTimeNow(FILETIME
*filetime
)
843 GetSystemTimeAsFileTime(filetime
);
847 /******************************************************************************
848 * CoCreateGuid (combase.@)
850 HRESULT WINAPI
CoCreateGuid(GUID
*guid
)
854 if (!guid
) return E_INVALIDARG
;
856 status
= UuidCreate(guid
);
857 if (status
== RPC_S_OK
|| status
== RPC_S_UUID_LOCAL_ONLY
) return S_OK
;
858 return HRESULT_FROM_WIN32(status
);
861 /******************************************************************************
862 * CoQueryProxyBlanket (combase.@)
864 HRESULT WINAPI
CoQueryProxyBlanket(IUnknown
*proxy
, DWORD
*authn_service
,
865 DWORD
*authz_service
, OLECHAR
**servername
, DWORD
*authn_level
,
866 DWORD
*imp_level
, void **auth_info
, DWORD
*capabilities
)
868 IClientSecurity
*client_security
;
871 TRACE("%p, %p, %p, %p, %p, %p, %p, %p.\n", proxy
, authn_service
, authz_service
, servername
, authn_level
, imp_level
,
872 auth_info
, capabilities
);
874 hr
= IUnknown_QueryInterface(proxy
, &IID_IClientSecurity
, (void **)&client_security
);
877 hr
= IClientSecurity_QueryBlanket(client_security
, proxy
, authn_service
, authz_service
, servername
,
878 authn_level
, imp_level
, auth_info
, capabilities
);
879 IClientSecurity_Release(client_security
);
882 if (FAILED(hr
)) ERR("-- failed with %#x.\n", hr
);
886 /******************************************************************************
887 * CoSetProxyBlanket (combase.@)
889 HRESULT WINAPI
CoSetProxyBlanket(IUnknown
*proxy
, DWORD authn_service
, DWORD authz_service
,
890 OLECHAR
*servername
, DWORD authn_level
, DWORD imp_level
, void *auth_info
, DWORD capabilities
)
892 IClientSecurity
*client_security
;
895 TRACE("%p, %u, %u, %p, %u, %u, %p, %#x.\n", proxy
, authn_service
, authz_service
, servername
,
896 authn_level
, imp_level
, auth_info
, capabilities
);
898 hr
= IUnknown_QueryInterface(proxy
, &IID_IClientSecurity
, (void **)&client_security
);
901 hr
= IClientSecurity_SetBlanket(client_security
, proxy
, authn_service
, authz_service
, servername
, authn_level
,
902 imp_level
, auth_info
, capabilities
);
903 IClientSecurity_Release(client_security
);
906 if (FAILED(hr
)) ERR("-- failed with %#x.\n", hr
);
910 /***********************************************************************
911 * CoCopyProxy (combase.@)
913 HRESULT WINAPI
CoCopyProxy(IUnknown
*proxy
, IUnknown
**proxy_copy
)
915 IClientSecurity
*client_security
;
918 TRACE("%p, %p.\n", proxy
, proxy_copy
);
920 hr
= IUnknown_QueryInterface(proxy
, &IID_IClientSecurity
, (void **)&client_security
);
923 hr
= IClientSecurity_CopyProxy(client_security
, proxy
, proxy_copy
);
924 IClientSecurity_Release(client_security
);
927 if (FAILED(hr
)) ERR("-- failed with %#x.\n", hr
);
931 /***********************************************************************
932 * CoQueryClientBlanket (combase.@)
934 HRESULT WINAPI
CoQueryClientBlanket(DWORD
*authn_service
, DWORD
*authz_service
, OLECHAR
**servername
,
935 DWORD
*authn_level
, DWORD
*imp_level
, RPC_AUTHZ_HANDLE
*privs
, DWORD
*capabilities
)
937 IServerSecurity
*server_security
;
940 TRACE("%p, %p, %p, %p, %p, %p, %p.\n", authn_service
, authz_service
, servername
, authn_level
, imp_level
,
941 privs
, capabilities
);
943 hr
= CoGetCallContext(&IID_IServerSecurity
, (void **)&server_security
);
946 hr
= IServerSecurity_QueryBlanket(server_security
, authn_service
, authz_service
, servername
, authn_level
,
947 imp_level
, privs
, capabilities
);
948 IServerSecurity_Release(server_security
);
954 /***********************************************************************
955 * CoImpersonateClient (combase.@)
957 HRESULT WINAPI
CoImpersonateClient(void)
959 IServerSecurity
*server_security
;
964 hr
= CoGetCallContext(&IID_IServerSecurity
, (void **)&server_security
);
967 hr
= IServerSecurity_ImpersonateClient(server_security
);
968 IServerSecurity_Release(server_security
);
974 /***********************************************************************
975 * CoRevertToSelf (combase.@)
977 HRESULT WINAPI
CoRevertToSelf(void)
979 IServerSecurity
*server_security
;
984 hr
= CoGetCallContext(&IID_IServerSecurity
, (void **)&server_security
);
987 hr
= IServerSecurity_RevertToSelf(server_security
);
988 IServerSecurity_Release(server_security
);
994 /***********************************************************************
995 * CoInitializeSecurity (combase.@)
997 HRESULT WINAPI
CoInitializeSecurity(PSECURITY_DESCRIPTOR sd
, LONG cAuthSvc
,
998 SOLE_AUTHENTICATION_SERVICE
*asAuthSvc
, void *reserved1
, DWORD authn_level
,
999 DWORD imp_level
, void *reserved2
, DWORD capabilities
, void *reserved3
)
1001 FIXME("%p, %d, %p, %p, %d, %d, %p, %d, %p stub\n", sd
, cAuthSvc
, asAuthSvc
, reserved1
, authn_level
,
1002 imp_level
, reserved2
, capabilities
, reserved3
);
1007 /***********************************************************************
1008 * CoGetObjectContext (combase.@)
1010 HRESULT WINAPI
CoGetObjectContext(REFIID riid
, void **ppv
)
1012 IObjContext
*context
;
1015 TRACE("%s, %p.\n", debugstr_guid(riid
), ppv
);
1018 hr
= CoGetContextToken((ULONG_PTR
*)&context
);
1022 return IObjContext_QueryInterface(context
, riid
, ppv
);
1025 /***********************************************************************
1026 * CoGetDefaultContext (combase.@)
1028 HRESULT WINAPI
CoGetDefaultContext(APTTYPE type
, REFIID riid
, void **obj
)
1030 FIXME("%d, %s, %p stub\n", type
, debugstr_guid(riid
), obj
);
1032 return E_NOINTERFACE
;
1035 /***********************************************************************
1036 * CoGetCallState (combase.@)
1038 HRESULT WINAPI
CoGetCallState(int arg1
, ULONG
*arg2
)
1040 FIXME("%d, %p.\n", arg1
, arg2
);
1045 /***********************************************************************
1046 * CoGetActivationState (combase.@)
1048 HRESULT WINAPI
CoGetActivationState(GUID guid
, DWORD arg2
, DWORD
*arg3
)
1050 FIXME("%s, %x, %p.\n", debugstr_guid(&guid
), arg2
, arg3
);
1055 /******************************************************************************
1056 * CoGetTreatAsClass (combase.@)
1058 HRESULT WINAPI
CoGetTreatAsClass(REFCLSID clsidOld
, CLSID
*clsidNew
)
1060 WCHAR buffW
[CHARS_IN_GUID
];
1061 LONG len
= sizeof(buffW
);
1065 TRACE("%s, %p.\n", debugstr_guid(clsidOld
), clsidNew
);
1067 if (!clsidOld
|| !clsidNew
)
1068 return E_INVALIDARG
;
1070 *clsidNew
= *clsidOld
;
1072 hr
= open_key_for_clsid(clsidOld
, L
"TreatAs", KEY_READ
, &hkey
);
1079 if (RegQueryValueW(hkey
, NULL
, buffW
, &len
))
1085 hr
= CLSIDFromString(buffW
, clsidNew
);
1087 ERR("Failed to get CLSID from string %s, hr %#x.\n", debugstr_w(buffW
), hr
);
1089 if (hkey
) RegCloseKey(hkey
);
1093 /******************************************************************************
1094 * ProgIDFromCLSID (combase.@)
1096 HRESULT WINAPI DECLSPEC_HOTPATCH
ProgIDFromCLSID(REFCLSID clsid
, LPOLESTR
*progid
)
1098 ACTCTX_SECTION_KEYED_DATA data
;
1104 return E_INVALIDARG
;
1108 data
.cbSize
= sizeof(data
);
1109 if (FindActCtxSectionGuid(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
,
1112 struct comclassredirect_data
*comclass
= (struct comclassredirect_data
*)data
.lpData
;
1113 if (comclass
->progid_len
)
1117 *progid
= CoTaskMemAlloc(comclass
->progid_len
+ sizeof(WCHAR
));
1118 if (!*progid
) return E_OUTOFMEMORY
;
1120 ptrW
= (WCHAR
*)((BYTE
*)comclass
+ comclass
->progid_offset
);
1121 memcpy(*progid
, ptrW
, comclass
->progid_len
+ sizeof(WCHAR
));
1125 return REGDB_E_CLASSNOTREG
;
1128 hr
= open_key_for_clsid(clsid
, L
"ProgID", KEY_READ
, &hkey
);
1132 if (RegQueryValueW(hkey
, NULL
, NULL
, &progidlen
))
1133 hr
= REGDB_E_CLASSNOTREG
;
1137 *progid
= CoTaskMemAlloc(progidlen
* sizeof(WCHAR
));
1140 if (RegQueryValueW(hkey
, NULL
, *progid
, &progidlen
))
1142 hr
= REGDB_E_CLASSNOTREG
;
1143 CoTaskMemFree(*progid
);
1155 static inline BOOL
is_valid_hex(WCHAR c
)
1157 if (!(((c
>= '0') && (c
<= '9')) ||
1158 ((c
>= 'a') && (c
<= 'f')) ||
1159 ((c
>= 'A') && (c
<= 'F'))))
1164 static const BYTE guid_conv_table
[256] =
1166 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
1167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
1168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
1169 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
1170 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
1171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
1172 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
1175 static BOOL
guid_from_string(LPCWSTR s
, GUID
*id
)
1179 if (!s
|| s
[0] != '{')
1181 memset(id
, 0, sizeof(*id
));
1182 if (!s
) return TRUE
;
1186 TRACE("%s -> %p\n", debugstr_w(s
), id
);
1188 /* In form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
1191 for (i
= 1; i
< 9; ++i
)
1193 if (!is_valid_hex(s
[i
])) return FALSE
;
1194 id
->Data1
= (id
->Data1
<< 4) | guid_conv_table
[s
[i
]];
1196 if (s
[9] != '-') return FALSE
;
1199 for (i
= 10; i
< 14; ++i
)
1201 if (!is_valid_hex(s
[i
])) return FALSE
;
1202 id
->Data2
= (id
->Data2
<< 4) | guid_conv_table
[s
[i
]];
1204 if (s
[14] != '-') return FALSE
;
1207 for (i
= 15; i
< 19; ++i
)
1209 if (!is_valid_hex(s
[i
])) return FALSE
;
1210 id
->Data3
= (id
->Data3
<< 4) | guid_conv_table
[s
[i
]];
1212 if (s
[19] != '-') return FALSE
;
1214 for (i
= 20; i
< 37; i
+= 2)
1218 if (s
[i
] != '-') return FALSE
;
1221 if (!is_valid_hex(s
[i
]) || !is_valid_hex(s
[i
+ 1])) return FALSE
;
1222 id
->Data4
[(i
- 20) / 2] = guid_conv_table
[s
[i
]] << 4 | guid_conv_table
[s
[i
+ 1]];
1225 if (s
[37] == '}' && s
[38] == '\0')
1231 static HRESULT
clsid_from_string_reg(LPCOLESTR progid
, CLSID
*clsid
)
1233 WCHAR buf2
[CHARS_IN_GUID
];
1234 LONG buf2len
= sizeof(buf2
);
1238 memset(clsid
, 0, sizeof(*clsid
));
1239 buf
= heap_alloc((lstrlenW(progid
) + 8) * sizeof(WCHAR
));
1240 if (!buf
) return E_OUTOFMEMORY
;
1242 lstrcpyW(buf
, progid
);
1243 lstrcatW(buf
, L
"\\CLSID");
1244 if (open_classes_key(HKEY_CLASSES_ROOT
, buf
, MAXIMUM_ALLOWED
, &xhkey
))
1247 WARN("couldn't open key for ProgID %s\n", debugstr_w(progid
));
1248 return CO_E_CLASSSTRING
;
1252 if (RegQueryValueW(xhkey
, NULL
, buf2
, &buf2len
))
1255 WARN("couldn't query clsid value for ProgID %s\n", debugstr_w(progid
));
1256 return CO_E_CLASSSTRING
;
1259 return guid_from_string(buf2
, clsid
) ? S_OK
: CO_E_CLASSSTRING
;
1262 /******************************************************************************
1263 * CLSIDFromProgID (combase.@)
1265 HRESULT WINAPI DECLSPEC_HOTPATCH
CLSIDFromProgID(LPCOLESTR progid
, CLSID
*clsid
)
1267 ACTCTX_SECTION_KEYED_DATA data
;
1269 if (!progid
|| !clsid
)
1270 return E_INVALIDARG
;
1272 data
.cbSize
= sizeof(data
);
1273 if (FindActCtxSectionStringW(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
,
1276 struct progidredirect_data
*progiddata
= (struct progidredirect_data
*)data
.lpData
;
1277 CLSID
*alias
= (CLSID
*)((BYTE
*)data
.lpSectionBase
+ progiddata
->clsid_offset
);
1282 return clsid_from_string_reg(progid
, clsid
);
1285 /******************************************************************************
1286 * CLSIDFromProgIDEx (combase.@)
1288 HRESULT WINAPI
CLSIDFromProgIDEx(LPCOLESTR progid
, CLSID
*clsid
)
1290 FIXME("%s, %p: semi-stub\n", debugstr_w(progid
), clsid
);
1292 return CLSIDFromProgID(progid
, clsid
);
1295 /******************************************************************************
1296 * CLSIDFromString (combase.@)
1298 HRESULT WINAPI
CLSIDFromString(LPCOLESTR str
, LPCLSID clsid
)
1304 return E_INVALIDARG
;
1306 if (guid_from_string(str
, clsid
))
1309 /* It appears a ProgID is also valid */
1310 hr
= clsid_from_string_reg(str
, &tmp_id
);
1317 /******************************************************************************
1318 * IIDFromString (combase.@)
1320 HRESULT WINAPI
IIDFromString(LPCOLESTR str
, IID
*iid
)
1322 TRACE("%s, %p\n", debugstr_w(str
), iid
);
1326 memset(iid
, 0, sizeof(*iid
));
1330 /* length mismatch is a special case */
1331 if (lstrlenW(str
) + 1 != CHARS_IN_GUID
)
1332 return E_INVALIDARG
;
1335 return CO_E_IIDSTRING
;
1337 return guid_from_string(str
, iid
) ? S_OK
: CO_E_IIDSTRING
;
1340 /******************************************************************************
1341 * StringFromCLSID (combase.@)
1343 HRESULT WINAPI
StringFromCLSID(REFCLSID clsid
, LPOLESTR
*str
)
1345 if (!(*str
= CoTaskMemAlloc(CHARS_IN_GUID
* sizeof(WCHAR
)))) return E_OUTOFMEMORY
;
1346 StringFromGUID2(clsid
, *str
, CHARS_IN_GUID
);
1350 /******************************************************************************
1351 * StringFromGUID2 (combase.@)
1353 INT WINAPI
StringFromGUID2(REFGUID guid
, LPOLESTR str
, INT cmax
)
1355 if (!guid
|| cmax
< CHARS_IN_GUID
) return 0;
1356 swprintf(str
, CHARS_IN_GUID
, L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", guid
->Data1
,
1357 guid
->Data2
, guid
->Data3
, guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
1358 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
1359 return CHARS_IN_GUID
;
1362 static void init_multi_qi(DWORD count
, MULTI_QI
*mqi
, HRESULT hr
)
1366 for (i
= 0; i
< count
; i
++)
1373 static HRESULT
return_multi_qi(IUnknown
*unk
, DWORD count
, MULTI_QI
*mqi
, BOOL include_unk
)
1375 ULONG index
= 0, fetched
= 0;
1381 index
= fetched
= 1;
1384 for (; index
< count
; index
++)
1386 mqi
[index
].hr
= IUnknown_QueryInterface(unk
, mqi
[index
].pIID
, (void **)&mqi
[index
].pItf
);
1387 if (mqi
[index
].hr
== S_OK
)
1392 IUnknown_Release(unk
);
1395 return E_NOINTERFACE
;
1397 return fetched
== count
? S_OK
: CO_S_NOTALLINTERFACES
;
1400 /***********************************************************************
1401 * CoGetInstanceFromFile (combase.@)
1403 HRESULT WINAPI DECLSPEC_HOTPATCH
CoGetInstanceFromFile(COSERVERINFO
*server_info
, CLSID
*rclsid
,
1404 IUnknown
*outer
, DWORD cls_context
, DWORD grfmode
, OLECHAR
*filename
, DWORD count
,
1407 IPersistFile
*pf
= NULL
;
1408 IUnknown
*obj
= NULL
;
1412 if (!count
|| !results
)
1413 return E_INVALIDARG
;
1416 FIXME("() non-NULL server_info not supported\n");
1418 init_multi_qi(count
, results
, E_NOINTERFACE
);
1422 hr
= GetClassFile(filename
, &clsid
);
1425 ERR("Failed to get CLSID from a file.\n");
1432 hr
= CoCreateInstance(rclsid
, outer
, cls_context
, &IID_IUnknown
, (void **)&obj
);
1435 init_multi_qi(count
, results
, hr
);
1439 /* Init from file */
1440 hr
= IUnknown_QueryInterface(obj
, &IID_IPersistFile
, (void **)&pf
);
1443 init_multi_qi(count
, results
, hr
);
1444 IUnknown_Release(obj
);
1448 hr
= IPersistFile_Load(pf
, filename
, grfmode
);
1449 IPersistFile_Release(pf
);
1451 return return_multi_qi(obj
, count
, results
, FALSE
);
1454 init_multi_qi(count
, results
, hr
);
1455 IUnknown_Release(obj
);
1460 /***********************************************************************
1461 * CoGetInstanceFromIStorage (combase.@)
1463 HRESULT WINAPI
CoGetInstanceFromIStorage(COSERVERINFO
*server_info
, CLSID
*rclsid
,
1464 IUnknown
*outer
, DWORD cls_context
, IStorage
*storage
, DWORD count
, MULTI_QI
*results
)
1466 IPersistStorage
*ps
= NULL
;
1467 IUnknown
*obj
= NULL
;
1471 if (!count
|| !results
|| !storage
)
1472 return E_INVALIDARG
;
1475 FIXME("() non-NULL server_info not supported\n");
1477 init_multi_qi(count
, results
, E_NOINTERFACE
);
1481 memset(&stat
.clsid
, 0, sizeof(stat
.clsid
));
1482 hr
= IStorage_Stat(storage
, &stat
, STATFLAG_NONAME
);
1485 ERR("Failed to get CLSID from a storage.\n");
1489 rclsid
= &stat
.clsid
;
1492 hr
= CoCreateInstance(rclsid
, outer
, cls_context
, &IID_IUnknown
, (void **)&obj
);
1496 /* Init from IStorage */
1497 hr
= IUnknown_QueryInterface(obj
, &IID_IPersistStorage
, (void **)&ps
);
1499 ERR("failed to get IPersistStorage\n");
1503 IPersistStorage_Load(ps
, storage
);
1504 IPersistStorage_Release(ps
);
1507 return return_multi_qi(obj
, count
, results
, FALSE
);
1510 /***********************************************************************
1511 * CoCreateInstance (combase.@)
1513 HRESULT WINAPI DECLSPEC_HOTPATCH
CoCreateInstance(REFCLSID rclsid
, IUnknown
*outer
, DWORD cls_context
,
1514 REFIID riid
, void **obj
)
1516 MULTI_QI multi_qi
= { .pIID
= riid
};
1519 TRACE("%s, %p, %#x, %s, %p.\n", debugstr_guid(rclsid
), outer
, cls_context
, debugstr_guid(riid
), obj
);
1524 hr
= CoCreateInstanceEx(rclsid
, outer
, cls_context
, NULL
, 1, &multi_qi
);
1525 *obj
= multi_qi
.pItf
;
1529 /***********************************************************************
1530 * CoCreateInstanceFromApp (combase.@)
1532 HRESULT WINAPI
CoCreateInstanceFromApp(REFCLSID rclsid
, IUnknown
*outer
, DWORD cls_context
,
1533 void *server_info
, ULONG count
, MULTI_QI
*results
)
1535 TRACE("%s, %p, %#x, %p, %u, %p\n", debugstr_guid(rclsid
), outer
, cls_context
, server_info
,
1538 return CoCreateInstanceEx(rclsid
, outer
, cls_context
| CLSCTX_APPCONTAINER
, server_info
,
1542 static HRESULT
com_get_class_object(REFCLSID rclsid
, DWORD clscontext
,
1543 COSERVERINFO
*server_info
, REFIID riid
, void **obj
)
1545 struct class_reg_data clsreg
= { 0 };
1546 HRESULT hr
= E_UNEXPECTED
;
1547 IUnknown
*registered_obj
;
1548 struct apartment
*apt
;
1551 return E_INVALIDARG
;
1555 if (!(apt
= apartment_get_current_or_mta()))
1557 ERR("apartment not initialised\n");
1558 return CO_E_NOTINITIALIZED
;
1562 FIXME("server_info name %s, authinfo %p\n", debugstr_w(server_info
->pwszName
), server_info
->pAuthInfo
);
1564 if (clscontext
& CLSCTX_INPROC_SERVER
)
1566 if (IsEqualCLSID(rclsid
, &CLSID_InProcFreeMarshaler
) ||
1567 IsEqualCLSID(rclsid
, &CLSID_GlobalOptions
) ||
1568 (!(clscontext
& CLSCTX_APPCONTAINER
) && IsEqualCLSID(rclsid
, &CLSID_ManualResetEvent
)) ||
1569 IsEqualCLSID(rclsid
, &CLSID_StdGlobalInterfaceTable
))
1571 apartment_release(apt
);
1572 return Ole32DllGetClassObject(rclsid
, riid
, obj
);
1576 if (clscontext
& CLSCTX_INPROC
)
1578 ACTCTX_SECTION_KEYED_DATA data
;
1580 data
.cbSize
= sizeof(data
);
1581 /* search activation context first */
1582 if (FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
, NULL
,
1583 ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
, rclsid
, &data
))
1585 struct comclassredirect_data
*comclass
= (struct comclassredirect_data
*)data
.lpData
;
1587 clsreg
.u
.actctx
.module_name
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ comclass
->name_offset
);
1588 clsreg
.u
.actctx
.hactctx
= data
.hActCtx
;
1589 clsreg
.u
.actctx
.threading_model
= comclass
->model
;
1590 clsreg
.origin
= CLASS_REG_ACTCTX
;
1592 hr
= apartment_get_inproc_class_object(apt
, &clsreg
, &comclass
->clsid
, riid
, clscontext
, obj
);
1593 ReleaseActCtx(data
.hActCtx
);
1594 apartment_release(apt
);
1600 * First, try and see if we can't match the class ID with one of the
1601 * registered classes.
1603 if (!(clscontext
& CLSCTX_APPCONTAINER
) && (registered_obj
= com_get_registered_class_object(apt
, rclsid
, clscontext
)))
1605 hr
= IUnknown_QueryInterface(registered_obj
, riid
, obj
);
1606 IUnknown_Release(registered_obj
);
1607 apartment_release(apt
);
1611 /* First try in-process server */
1612 if (clscontext
& CLSCTX_INPROC_SERVER
)
1616 hr
= open_key_for_clsid(rclsid
, L
"InprocServer32", KEY_READ
, &hkey
);
1619 if (hr
== REGDB_E_CLASSNOTREG
)
1620 ERR("class %s not registered\n", debugstr_guid(rclsid
));
1621 else if (hr
== REGDB_E_KEYMISSING
)
1623 WARN("class %s not registered as in-proc server\n", debugstr_guid(rclsid
));
1624 hr
= REGDB_E_CLASSNOTREG
;
1630 clsreg
.u
.hkey
= hkey
;
1631 clsreg
.origin
= CLASS_REG_REGISTRY
;
1633 hr
= apartment_get_inproc_class_object(apt
, &clsreg
, rclsid
, riid
, clscontext
, obj
);
1637 /* return if we got a class, otherwise fall through to one of the
1641 apartment_release(apt
);
1646 /* Next try in-process handler */
1647 if (clscontext
& CLSCTX_INPROC_HANDLER
)
1651 hr
= open_key_for_clsid(rclsid
, L
"InprocHandler32", KEY_READ
, &hkey
);
1654 if (hr
== REGDB_E_CLASSNOTREG
)
1655 ERR("class %s not registered\n", debugstr_guid(rclsid
));
1656 else if (hr
== REGDB_E_KEYMISSING
)
1658 WARN("class %s not registered in-proc handler\n", debugstr_guid(rclsid
));
1659 hr
= REGDB_E_CLASSNOTREG
;
1665 clsreg
.u
.hkey
= hkey
;
1666 clsreg
.origin
= CLASS_REG_REGISTRY
;
1668 hr
= apartment_get_inproc_class_object(apt
, &clsreg
, rclsid
, riid
, clscontext
, obj
);
1672 /* return if we got a class, otherwise fall through to one of the
1676 apartment_release(apt
);
1680 apartment_release(apt
);
1682 /* Next try out of process */
1683 if (clscontext
& CLSCTX_LOCAL_SERVER
)
1685 hr
= rpc_get_local_class_object(rclsid
, riid
, obj
);
1690 /* Finally try remote: this requires networked DCOM (a lot of work) */
1691 if (clscontext
& CLSCTX_REMOTE_SERVER
)
1693 FIXME ("CLSCTX_REMOTE_SERVER not supported\n");
1694 hr
= REGDB_E_CLASSNOTREG
;
1698 ERR("no class object %s could be created for context %#x\n", debugstr_guid(rclsid
), clscontext
);
1703 /***********************************************************************
1704 * CoCreateInstanceEx (combase.@)
1706 HRESULT WINAPI DECLSPEC_HOTPATCH
CoCreateInstanceEx(REFCLSID rclsid
, IUnknown
*outer
, DWORD cls_context
,
1707 COSERVERINFO
*server_info
, ULONG count
, MULTI_QI
*results
)
1709 IClassFactory
*factory
;
1710 IUnknown
*unk
= NULL
;
1714 TRACE("%s, %p, %#x, %p, %u, %p\n", debugstr_guid(rclsid
), outer
, cls_context
, server_info
, count
, results
);
1716 if (!count
|| !results
)
1717 return E_INVALIDARG
;
1720 FIXME("Server info is not supported.\n");
1722 init_multi_qi(count
, results
, E_NOINTERFACE
);
1725 if (!(cls_context
& CLSCTX_APPCONTAINER
))
1726 CoGetTreatAsClass(rclsid
, &clsid
);
1728 if (FAILED(hr
= com_get_class_object(&clsid
, cls_context
, NULL
, &IID_IClassFactory
, (void **)&factory
)))
1731 hr
= IClassFactory_CreateInstance(factory
, outer
, results
[0].pIID
, (void **)&unk
);
1732 IClassFactory_Release(factory
);
1735 if (hr
== CLASS_E_NOAGGREGATION
&& outer
)
1736 FIXME("Class %s does not support aggregation\n", debugstr_guid(&clsid
));
1738 FIXME("no instance created for interface %s of class %s, hr %#x.\n",
1739 debugstr_guid(results
[0].pIID
), debugstr_guid(&clsid
), hr
);
1743 return return_multi_qi(unk
, count
, results
, TRUE
);
1746 /***********************************************************************
1747 * CoGetClassObject (combase.@)
1749 HRESULT WINAPI DECLSPEC_HOTPATCH
CoGetClassObject(REFCLSID rclsid
, DWORD clscontext
,
1750 COSERVERINFO
*server_info
, REFIID riid
, void **obj
)
1752 TRACE("%s, %#x, %s\n", debugstr_guid(rclsid
), clscontext
, debugstr_guid(riid
));
1754 return com_get_class_object(rclsid
, clscontext
, server_info
, riid
, obj
);
1757 /***********************************************************************
1758 * CoFreeUnusedLibraries (combase.@)
1760 void WINAPI DECLSPEC_HOTPATCH
CoFreeUnusedLibraries(void)
1762 CoFreeUnusedLibrariesEx(INFINITE
, 0);
1765 /***********************************************************************
1766 * CoGetCallContext (combase.@)
1768 HRESULT WINAPI
CoGetCallContext(REFIID riid
, void **obj
)
1770 struct tlsdata
*tlsdata
;
1773 TRACE("%s, %p\n", debugstr_guid(riid
), obj
);
1775 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1778 if (!tlsdata
->call_state
)
1779 return RPC_E_CALL_COMPLETE
;
1781 return IUnknown_QueryInterface(tlsdata
->call_state
, riid
, obj
);
1784 /***********************************************************************
1785 * CoSwitchCallContext (combase.@)
1787 HRESULT WINAPI
CoSwitchCallContext(IUnknown
*context
, IUnknown
**old_context
)
1789 struct tlsdata
*tlsdata
;
1792 TRACE("%p, %p\n", context
, old_context
);
1794 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1797 /* Reference counts are not touched. */
1798 *old_context
= tlsdata
->call_state
;
1799 tlsdata
->call_state
= context
;
1804 /******************************************************************************
1805 * CoRegisterInitializeSpy (combase.@)
1807 HRESULT WINAPI
CoRegisterInitializeSpy(IInitializeSpy
*spy
, ULARGE_INTEGER
*cookie
)
1809 struct tlsdata
*tlsdata
;
1810 struct init_spy
*entry
;
1814 TRACE("%p, %p\n", spy
, cookie
);
1816 if (!spy
|| !cookie
)
1817 return E_INVALIDARG
;
1819 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1822 hr
= IInitializeSpy_QueryInterface(spy
, &IID_IInitializeSpy
, (void **)&spy
);
1826 entry
= heap_alloc(sizeof(*entry
));
1829 IInitializeSpy_Release(spy
);
1830 return E_OUTOFMEMORY
;
1836 while (get_spy_entry(tlsdata
, id
) != NULL
)
1842 list_add_head(&tlsdata
->spies
, &entry
->entry
);
1844 cookie
->u
.HighPart
= GetCurrentThreadId();
1845 cookie
->u
.LowPart
= entry
->id
;
1850 /******************************************************************************
1851 * CoRevokeInitializeSpy (combase.@)
1853 HRESULT WINAPI
CoRevokeInitializeSpy(ULARGE_INTEGER cookie
)
1855 struct tlsdata
*tlsdata
;
1856 struct init_spy
*spy
;
1859 TRACE("%s\n", wine_dbgstr_longlong(cookie
.QuadPart
));
1861 if (cookie
.u
.HighPart
!= GetCurrentThreadId())
1862 return E_INVALIDARG
;
1864 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1867 if (!(spy
= get_spy_entry(tlsdata
, cookie
.u
.LowPart
))) return E_INVALIDARG
;
1869 IInitializeSpy_Release(spy
->spy
);
1871 if (!tlsdata
->spies_lock
)
1873 list_remove(&spy
->entry
);
1879 static BOOL
com_peek_message(struct apartment
*apt
, MSG
*msg
)
1881 /* First try to retrieve messages for incoming COM calls to the apartment window */
1882 return (apt
->win
&& PeekMessageW(msg
, apt
->win
, 0, 0, PM_REMOVE
| PM_NOYIELD
)) ||
1883 /* Next retrieve other messages necessary for the app to remain responsive */
1884 PeekMessageW(msg
, NULL
, WM_DDE_FIRST
, WM_DDE_LAST
, PM_REMOVE
| PM_NOYIELD
) ||
1885 PeekMessageW(msg
, NULL
, 0, 0, PM_QS_PAINT
| PM_QS_SENDMESSAGE
| PM_REMOVE
| PM_NOYIELD
);
1888 /***********************************************************************
1889 * CoWaitForMultipleHandles (combase.@)
1891 HRESULT WINAPI
CoWaitForMultipleHandles(DWORD flags
, DWORD timeout
, ULONG handle_count
, HANDLE
*handles
,
1894 BOOL check_apc
= !!(flags
& COWAIT_ALERTABLE
), post_quit
= FALSE
, message_loop
;
1895 DWORD start_time
, wait_flags
= 0;
1896 struct tlsdata
*tlsdata
;
1897 struct apartment
*apt
;
1901 TRACE("%#x, %#x, %u, %p, %p\n", flags
, timeout
, handle_count
, handles
, index
);
1904 return E_INVALIDARG
;
1909 return E_INVALIDARG
;
1912 return RPC_E_NO_SYNC
;
1914 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1917 apt
= com_get_current_apt();
1918 message_loop
= apt
&& !apt
->multi_threaded
;
1920 if (flags
& COWAIT_WAITALL
)
1921 wait_flags
|= MWMO_WAITALL
;
1922 if (flags
& COWAIT_ALERTABLE
)
1923 wait_flags
|= MWMO_ALERTABLE
;
1925 start_time
= GetTickCount();
1929 DWORD now
= GetTickCount(), res
;
1931 if (now
- start_time
> timeout
)
1933 hr
= RPC_S_CALLPENDING
;
1939 TRACE("waiting for rpc completion or window message\n");
1945 res
= WaitForMultipleObjectsEx(handle_count
, handles
, !!(flags
& COWAIT_WAITALL
), 0, TRUE
);
1949 if (res
== WAIT_TIMEOUT
)
1950 res
= MsgWaitForMultipleObjectsEx(handle_count
, handles
,
1951 timeout
== INFINITE
? INFINITE
: start_time
+ timeout
- now
,
1952 QS_SENDMESSAGE
| QS_ALLPOSTMESSAGE
| QS_PAINT
, wait_flags
);
1954 if (res
== WAIT_OBJECT_0
+ handle_count
) /* messages available */
1959 /* call message filter */
1963 PENDINGTYPE pendingtype
= tlsdata
->pending_call_count_server
? PENDINGTYPE_NESTED
: PENDINGTYPE_TOPLEVEL
;
1964 DWORD be_handled
= IMessageFilter_MessagePending(apt
->filter
, 0 /* FIXME */, now
- start_time
, pendingtype
);
1966 TRACE("IMessageFilter_MessagePending returned %d\n", be_handled
);
1970 case PENDINGMSG_CANCELCALL
:
1971 WARN("call canceled\n");
1972 hr
= RPC_E_CALL_CANCELED
;
1974 case PENDINGMSG_WAITNOPROCESS
:
1975 case PENDINGMSG_WAITDEFPROCESS
:
1977 /* FIXME: MSDN is very vague about the difference
1978 * between WAITNOPROCESS and WAITDEFPROCESS - there
1979 * appears to be none, so it is possibly a left-over
1980 * from the 16-bit world. */
1987 /* If window is NULL on apartment, peek at messages so that it will not trigger
1988 * MsgWaitForMultipleObjects next time. */
1989 PeekMessageW(NULL
, NULL
, 0, 0, PM_QS_POSTMESSAGE
| PM_NOREMOVE
| PM_NOYIELD
);
1992 /* Some apps (e.g. Visio 2010) don't handle WM_PAINT properly and loop forever,
1993 * so after processing 100 messages we go back to checking the wait handles */
1994 while (msg_count
++ < 100 && com_peek_message(apt
, &msg
))
1996 if (msg
.message
== WM_QUIT
)
1998 TRACE("Received WM_QUIT message\n");
2000 exit_code
= msg
.wParam
;
2004 TRACE("Received message whilst waiting for RPC: 0x%04x\n", msg
.message
);
2005 TranslateMessage(&msg
);
2006 DispatchMessageW(&msg
);
2014 TRACE("Waiting for rpc completion\n");
2016 res
= WaitForMultipleObjectsEx(handle_count
, handles
, !!(flags
& COWAIT_WAITALL
),
2017 (timeout
== INFINITE
) ? INFINITE
: start_time
+ timeout
- now
, !!(flags
& COWAIT_ALERTABLE
));
2023 hr
= RPC_S_CALLPENDING
;
2026 hr
= HRESULT_FROM_WIN32(GetLastError());
2034 if (post_quit
) PostQuitMessage(exit_code
);
2036 TRACE("-- 0x%08x\n", hr
);
2041 /******************************************************************************
2042 * CoRegisterMessageFilter (combase.@)
2044 HRESULT WINAPI
CoRegisterMessageFilter(IMessageFilter
*filter
, IMessageFilter
**ret_filter
)
2046 IMessageFilter
*old_filter
;
2047 struct apartment
*apt
;
2049 TRACE("%p, %p\n", filter
, ret_filter
);
2051 apt
= com_get_current_apt();
2053 /* Can't set a message filter in a multi-threaded apartment */
2054 if (!apt
|| apt
->multi_threaded
)
2056 WARN("Can't set message filter in MTA or uninitialized apt\n");
2057 return CO_E_NOT_SUPPORTED
;
2061 IMessageFilter_AddRef(filter
);
2063 EnterCriticalSection(&apt
->cs
);
2065 old_filter
= apt
->filter
;
2066 apt
->filter
= filter
;
2068 LeaveCriticalSection(&apt
->cs
);
2071 *ret_filter
= old_filter
;
2072 else if (old_filter
)
2073 IMessageFilter_Release(old_filter
);
2078 static void com_revoke_all_ps_clsids(void)
2080 struct registered_ps
*cur
, *cur2
;
2082 EnterCriticalSection(&cs_registered_ps
);
2084 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, ®istered_proxystubs
, struct registered_ps
, entry
)
2086 list_remove(&cur
->entry
);
2090 LeaveCriticalSection(&cs_registered_ps
);
2093 static HRESULT
get_ps_clsid_from_registry(const WCHAR
* path
, REGSAM access
, CLSID
*pclsid
)
2095 WCHAR value
[CHARS_IN_GUID
];
2101 if (open_classes_key(HKEY_CLASSES_ROOT
, path
, access
, &hkey
))
2102 return REGDB_E_IIDNOTREG
;
2104 len
= sizeof(value
);
2105 if (ERROR_SUCCESS
!= RegQueryValueExW(hkey
, NULL
, NULL
, NULL
, (BYTE
*)value
, &len
))
2106 return REGDB_E_IIDNOTREG
;
2109 if (CLSIDFromString(value
, pclsid
) != NOERROR
)
2110 return REGDB_E_IIDNOTREG
;
2115 /*****************************************************************************
2116 * CoGetPSClsid (combase.@)
2118 HRESULT WINAPI
CoGetPSClsid(REFIID riid
, CLSID
*pclsid
)
2120 static const WCHAR interfaceW
[] = L
"Interface\\";
2121 static const WCHAR psW
[] = L
"\\ProxyStubClsid32";
2122 WCHAR path
[ARRAY_SIZE(interfaceW
) - 1 + CHARS_IN_GUID
- 1 + ARRAY_SIZE(psW
)];
2123 ACTCTX_SECTION_KEYED_DATA data
;
2124 struct registered_ps
*cur
;
2125 REGSAM opposite
= (sizeof(void*) > sizeof(int)) ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
;
2129 TRACE("%s, %p\n", debugstr_guid(riid
), pclsid
);
2131 if (!InternalIsProcessInitialized())
2133 ERR("apartment not initialised\n");
2134 return CO_E_NOTINITIALIZED
;
2138 return E_INVALIDARG
;
2140 EnterCriticalSection(&cs_registered_ps
);
2142 LIST_FOR_EACH_ENTRY(cur
, ®istered_proxystubs
, struct registered_ps
, entry
)
2144 if (IsEqualIID(&cur
->iid
, riid
))
2146 *pclsid
= cur
->clsid
;
2147 LeaveCriticalSection(&cs_registered_ps
);
2152 LeaveCriticalSection(&cs_registered_ps
);
2154 data
.cbSize
= sizeof(data
);
2155 if (FindActCtxSectionGuid(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
,
2158 struct ifacepsredirect_data
*ifaceps
= (struct ifacepsredirect_data
*)data
.lpData
;
2159 *pclsid
= ifaceps
->iid
;
2163 /* Interface\\{string form of riid}\\ProxyStubClsid32 */
2164 lstrcpyW(path
, interfaceW
);
2165 StringFromGUID2(riid
, path
+ ARRAY_SIZE(interfaceW
) - 1, CHARS_IN_GUID
);
2166 lstrcpyW(path
+ ARRAY_SIZE(interfaceW
) - 1 + CHARS_IN_GUID
- 1, psW
);
2168 hr
= get_ps_clsid_from_registry(path
, 0, pclsid
);
2169 if (FAILED(hr
) && (opposite
== KEY_WOW64_32KEY
|| (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)))
2170 hr
= get_ps_clsid_from_registry(path
, opposite
, pclsid
);
2173 TRACE("() Returning CLSID %s\n", debugstr_guid(pclsid
));
2175 WARN("No PSFactoryBuffer object is registered for IID %s\n", debugstr_guid(riid
));
2180 /*****************************************************************************
2181 * CoRegisterPSClsid (combase.@)
2183 HRESULT WINAPI
CoRegisterPSClsid(REFIID riid
, REFCLSID rclsid
)
2185 struct registered_ps
*cur
;
2187 TRACE("%s, %s\n", debugstr_guid(riid
), debugstr_guid(rclsid
));
2189 if (!InternalIsProcessInitialized())
2191 ERR("apartment not initialised\n");
2192 return CO_E_NOTINITIALIZED
;
2195 EnterCriticalSection(&cs_registered_ps
);
2197 LIST_FOR_EACH_ENTRY(cur
, ®istered_proxystubs
, struct registered_ps
, entry
)
2199 if (IsEqualIID(&cur
->iid
, riid
))
2201 cur
->clsid
= *rclsid
;
2202 LeaveCriticalSection(&cs_registered_ps
);
2207 cur
= heap_alloc(sizeof(*cur
));
2210 LeaveCriticalSection(&cs_registered_ps
);
2211 return E_OUTOFMEMORY
;
2215 cur
->clsid
= *rclsid
;
2216 list_add_head(®istered_proxystubs
, &cur
->entry
);
2218 LeaveCriticalSection(&cs_registered_ps
);
2223 struct thread_context
2225 IComThreadingInfo IComThreadingInfo_iface
;
2226 IContextCallback IContextCallback_iface
;
2227 IObjContext IObjContext_iface
;
2231 static inline struct thread_context
*impl_from_IComThreadingInfo(IComThreadingInfo
*iface
)
2233 return CONTAINING_RECORD(iface
, struct thread_context
, IComThreadingInfo_iface
);
2236 static inline struct thread_context
*impl_from_IContextCallback(IContextCallback
*iface
)
2238 return CONTAINING_RECORD(iface
, struct thread_context
, IContextCallback_iface
);
2241 static inline struct thread_context
*impl_from_IObjContext(IObjContext
*iface
)
2243 return CONTAINING_RECORD(iface
, struct thread_context
, IObjContext_iface
);
2246 static HRESULT WINAPI
thread_context_info_QueryInterface(IComThreadingInfo
*iface
, REFIID riid
, void **obj
)
2248 struct thread_context
*context
= impl_from_IComThreadingInfo(iface
);
2252 if (IsEqualIID(riid
, &IID_IComThreadingInfo
) ||
2253 IsEqualIID(riid
, &IID_IUnknown
))
2255 *obj
= &context
->IComThreadingInfo_iface
;
2257 else if (IsEqualIID(riid
, &IID_IContextCallback
))
2259 *obj
= &context
->IContextCallback_iface
;
2261 else if (IsEqualIID(riid
, &IID_IObjContext
))
2263 *obj
= &context
->IObjContext_iface
;
2268 IUnknown_AddRef((IUnknown
*)*obj
);
2272 FIXME("interface not implemented %s\n", debugstr_guid(riid
));
2273 return E_NOINTERFACE
;
2276 static ULONG WINAPI
thread_context_info_AddRef(IComThreadingInfo
*iface
)
2278 struct thread_context
*context
= impl_from_IComThreadingInfo(iface
);
2279 return InterlockedIncrement(&context
->refcount
);
2282 static ULONG WINAPI
thread_context_info_Release(IComThreadingInfo
*iface
)
2284 struct thread_context
*context
= impl_from_IComThreadingInfo(iface
);
2286 /* Context instance is initially created with CoGetContextToken() with refcount set to 0,
2287 releasing context while refcount is at 0 destroys it. */
2288 if (!context
->refcount
)
2294 return InterlockedDecrement(&context
->refcount
);
2297 static HRESULT WINAPI
thread_context_info_GetCurrentApartmentType(IComThreadingInfo
*iface
, APTTYPE
*apttype
)
2299 APTTYPEQUALIFIER qualifier
;
2301 TRACE("%p\n", apttype
);
2303 return CoGetApartmentType(apttype
, &qualifier
);
2306 static HRESULT WINAPI
thread_context_info_GetCurrentThreadType(IComThreadingInfo
*iface
, THDTYPE
*thdtype
)
2308 APTTYPEQUALIFIER qualifier
;
2312 hr
= CoGetApartmentType(&apttype
, &qualifier
);
2316 TRACE("%p\n", thdtype
);
2321 case APTTYPE_MAINSTA
:
2322 *thdtype
= THDTYPE_PROCESSMESSAGES
;
2325 *thdtype
= THDTYPE_BLOCKMESSAGES
;
2331 static HRESULT WINAPI
thread_context_info_GetCurrentLogicalThreadId(IComThreadingInfo
*iface
, GUID
*logical_thread_id
)
2333 TRACE("%p\n", logical_thread_id
);
2335 return CoGetCurrentLogicalThreadId(logical_thread_id
);
2338 static HRESULT WINAPI
thread_context_info_SetCurrentLogicalThreadId(IComThreadingInfo
*iface
, REFGUID logical_thread_id
)
2340 FIXME("%s stub\n", debugstr_guid(logical_thread_id
));
2345 static const IComThreadingInfoVtbl thread_context_info_vtbl
=
2347 thread_context_info_QueryInterface
,
2348 thread_context_info_AddRef
,
2349 thread_context_info_Release
,
2350 thread_context_info_GetCurrentApartmentType
,
2351 thread_context_info_GetCurrentThreadType
,
2352 thread_context_info_GetCurrentLogicalThreadId
,
2353 thread_context_info_SetCurrentLogicalThreadId
2356 static HRESULT WINAPI
thread_context_callback_QueryInterface(IContextCallback
*iface
, REFIID riid
, void **obj
)
2358 struct thread_context
*context
= impl_from_IContextCallback(iface
);
2359 return IComThreadingInfo_QueryInterface(&context
->IComThreadingInfo_iface
, riid
, obj
);
2362 static ULONG WINAPI
thread_context_callback_AddRef(IContextCallback
*iface
)
2364 struct thread_context
*context
= impl_from_IContextCallback(iface
);
2365 return IComThreadingInfo_AddRef(&context
->IComThreadingInfo_iface
);
2368 static ULONG WINAPI
thread_context_callback_Release(IContextCallback
*iface
)
2370 struct thread_context
*context
= impl_from_IContextCallback(iface
);
2371 return IComThreadingInfo_Release(&context
->IComThreadingInfo_iface
);
2374 static HRESULT WINAPI
thread_context_callback_ContextCallback(IContextCallback
*iface
,
2375 PFNCONTEXTCALL callback
, ComCallData
*param
, REFIID riid
, int method
, IUnknown
*punk
)
2377 FIXME("%p, %p, %p, %s, %d, %p\n", iface
, callback
, param
, debugstr_guid(riid
), method
, punk
);
2382 static const IContextCallbackVtbl thread_context_callback_vtbl
=
2384 thread_context_callback_QueryInterface
,
2385 thread_context_callback_AddRef
,
2386 thread_context_callback_Release
,
2387 thread_context_callback_ContextCallback
2390 static HRESULT WINAPI
thread_object_context_QueryInterface(IObjContext
*iface
, REFIID riid
, void **obj
)
2392 struct thread_context
*context
= impl_from_IObjContext(iface
);
2393 return IComThreadingInfo_QueryInterface(&context
->IComThreadingInfo_iface
, riid
, obj
);
2396 static ULONG WINAPI
thread_object_context_AddRef(IObjContext
*iface
)
2398 struct thread_context
*context
= impl_from_IObjContext(iface
);
2399 return IComThreadingInfo_AddRef(&context
->IComThreadingInfo_iface
);
2402 static ULONG WINAPI
thread_object_context_Release(IObjContext
*iface
)
2404 struct thread_context
*context
= impl_from_IObjContext(iface
);
2405 return IComThreadingInfo_Release(&context
->IComThreadingInfo_iface
);
2408 static HRESULT WINAPI
thread_object_context_SetProperty(IObjContext
*iface
, REFGUID propid
, CPFLAGS flags
, IUnknown
*punk
)
2410 FIXME("%p, %s, %x, %p\n", iface
, debugstr_guid(propid
), flags
, punk
);
2415 static HRESULT WINAPI
thread_object_context_RemoveProperty(IObjContext
*iface
, REFGUID propid
)
2417 FIXME("%p, %s\n", iface
, debugstr_guid(propid
));
2422 static HRESULT WINAPI
thread_object_context_GetProperty(IObjContext
*iface
, REFGUID propid
, CPFLAGS
*flags
, IUnknown
**punk
)
2424 FIXME("%p, %s, %p, %p\n", iface
, debugstr_guid(propid
), flags
, punk
);
2429 static HRESULT WINAPI
thread_object_context_EnumContextProps(IObjContext
*iface
, IEnumContextProps
**props
)
2431 FIXME("%p, %p\n", iface
, props
);
2436 static void WINAPI
thread_object_context_Reserved1(IObjContext
*iface
)
2438 FIXME("%p\n", iface
);
2441 static void WINAPI
thread_object_context_Reserved2(IObjContext
*iface
)
2443 FIXME("%p\n", iface
);
2446 static void WINAPI
thread_object_context_Reserved3(IObjContext
*iface
)
2448 FIXME("%p\n", iface
);
2451 static void WINAPI
thread_object_context_Reserved4(IObjContext
*iface
)
2453 FIXME("%p\n", iface
);
2456 static void WINAPI
thread_object_context_Reserved5(IObjContext
*iface
)
2458 FIXME("%p\n", iface
);
2461 static void WINAPI
thread_object_context_Reserved6(IObjContext
*iface
)
2463 FIXME("%p\n", iface
);
2466 static void WINAPI
thread_object_context_Reserved7(IObjContext
*iface
)
2468 FIXME("%p\n", iface
);
2471 static const IObjContextVtbl thread_object_context_vtbl
=
2473 thread_object_context_QueryInterface
,
2474 thread_object_context_AddRef
,
2475 thread_object_context_Release
,
2476 thread_object_context_SetProperty
,
2477 thread_object_context_RemoveProperty
,
2478 thread_object_context_GetProperty
,
2479 thread_object_context_EnumContextProps
,
2480 thread_object_context_Reserved1
,
2481 thread_object_context_Reserved2
,
2482 thread_object_context_Reserved3
,
2483 thread_object_context_Reserved4
,
2484 thread_object_context_Reserved5
,
2485 thread_object_context_Reserved6
,
2486 thread_object_context_Reserved7
2489 /***********************************************************************
2490 * CoGetContextToken (combase.@)
2492 HRESULT WINAPI
CoGetContextToken(ULONG_PTR
*token
)
2494 struct tlsdata
*tlsdata
;
2497 TRACE("%p\n", token
);
2499 if (!InternalIsProcessInitialized())
2501 ERR("apartment not initialised\n");
2502 return CO_E_NOTINITIALIZED
;
2505 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
2511 if (!tlsdata
->context_token
)
2513 struct thread_context
*context
;
2515 context
= heap_alloc_zero(sizeof(*context
));
2517 return E_OUTOFMEMORY
;
2519 context
->IComThreadingInfo_iface
.lpVtbl
= &thread_context_info_vtbl
;
2520 context
->IContextCallback_iface
.lpVtbl
= &thread_context_callback_vtbl
;
2521 context
->IObjContext_iface
.lpVtbl
= &thread_object_context_vtbl
;
2522 /* Context token does not take a reference, it's always zero until the
2523 interface is explicitly requested with CoGetObjectContext(). */
2524 context
->refcount
= 0;
2526 tlsdata
->context_token
= &context
->IObjContext_iface
;
2529 *token
= (ULONG_PTR
)tlsdata
->context_token
;
2530 TRACE("context_token %p\n", tlsdata
->context_token
);
2535 /***********************************************************************
2536 * CoGetCurrentLogicalThreadId (combase.@)
2538 HRESULT WINAPI
CoGetCurrentLogicalThreadId(GUID
*id
)
2540 struct tlsdata
*tlsdata
;
2544 return E_INVALIDARG
;
2546 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
2549 if (IsEqualGUID(&tlsdata
->causality_id
, &GUID_NULL
))
2551 CoCreateGuid(&tlsdata
->causality_id
);
2552 tlsdata
->flags
|= OLETLS_UUIDINITIALIZED
;
2555 *id
= tlsdata
->causality_id
;
2560 /******************************************************************************
2561 * CoGetCurrentProcess (combase.@)
2563 DWORD WINAPI
CoGetCurrentProcess(void)
2565 struct tlsdata
*tlsdata
;
2567 if (FAILED(com_get_tlsdata(&tlsdata
)))
2570 if (!tlsdata
->thread_seqid
)
2571 rpcss_get_next_seqid(&tlsdata
->thread_seqid
);
2573 return tlsdata
->thread_seqid
;
2576 /***********************************************************************
2577 * CoFreeUnusedLibrariesEx (combase.@)
2579 void WINAPI DECLSPEC_HOTPATCH
CoFreeUnusedLibrariesEx(DWORD unload_delay
, DWORD reserved
)
2581 struct apartment
*apt
= com_get_current_apt();
2584 ERR("apartment not initialised\n");
2588 apartment_freeunusedlibraries(apt
, unload_delay
);
2592 * When locked, don't modify list (unless we add a new head), so that it's
2593 * safe to iterate it. Freeing of list entries is delayed and done on unlock.
2595 static inline void lock_init_spies(struct tlsdata
*tlsdata
)
2597 tlsdata
->spies_lock
++;
2600 static void unlock_init_spies(struct tlsdata
*tlsdata
)
2602 struct init_spy
*spy
, *next
;
2604 if (--tlsdata
->spies_lock
) return;
2606 LIST_FOR_EACH_ENTRY_SAFE(spy
, next
, &tlsdata
->spies
, struct init_spy
, entry
)
2608 if (spy
->spy
) continue;
2609 list_remove(&spy
->entry
);
2614 /******************************************************************************
2615 * CoInitializeWOW (combase.@)
2617 HRESULT WINAPI
CoInitializeWOW(DWORD arg1
, DWORD arg2
)
2619 FIXME("%#x, %#x\n", arg1
, arg2
);
2624 /******************************************************************************
2625 * CoInitializeEx (combase.@)
2627 HRESULT WINAPI DECLSPEC_HOTPATCH
CoInitializeEx(void *reserved
, DWORD model
)
2629 struct tlsdata
*tlsdata
;
2630 struct init_spy
*cursor
;
2633 TRACE("%p, %#x\n", reserved
, model
);
2636 WARN("Unexpected reserved argument %p\n", reserved
);
2638 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
2641 if (InterlockedExchangeAdd(&com_lockcount
, 1) == 0)
2642 TRACE("Initializing the COM libraries\n");
2644 lock_init_spies(tlsdata
);
2645 LIST_FOR_EACH_ENTRY(cursor
, &tlsdata
->spies
, struct init_spy
, entry
)
2647 if (cursor
->spy
) IInitializeSpy_PreInitialize(cursor
->spy
, model
, tlsdata
->inits
);
2649 unlock_init_spies(tlsdata
);
2651 hr
= enter_apartment(tlsdata
, model
);
2653 lock_init_spies(tlsdata
);
2654 LIST_FOR_EACH_ENTRY(cursor
, &tlsdata
->spies
, struct init_spy
, entry
)
2656 if (cursor
->spy
) hr
= IInitializeSpy_PostInitialize(cursor
->spy
, hr
, model
, tlsdata
->inits
);
2658 unlock_init_spies(tlsdata
);
2663 /***********************************************************************
2664 * CoUninitialize (combase.@)
2666 void WINAPI DECLSPEC_HOTPATCH
CoUninitialize(void)
2668 struct tlsdata
*tlsdata
;
2669 struct init_spy
*cursor
, *next
;
2674 if (FAILED(com_get_tlsdata(&tlsdata
)))
2677 lock_init_spies(tlsdata
);
2678 LIST_FOR_EACH_ENTRY_SAFE(cursor
, next
, &tlsdata
->spies
, struct init_spy
, entry
)
2680 if (cursor
->spy
) IInitializeSpy_PreUninitialize(cursor
->spy
, tlsdata
->inits
);
2682 unlock_init_spies(tlsdata
);
2685 if (!tlsdata
->inits
)
2687 ERR("Mismatched CoUninitialize\n");
2689 lock_init_spies(tlsdata
);
2690 LIST_FOR_EACH_ENTRY_SAFE(cursor
, next
, &tlsdata
->spies
, struct init_spy
, entry
)
2692 if (cursor
->spy
) IInitializeSpy_PostUninitialize(cursor
->spy
, tlsdata
->inits
);
2694 unlock_init_spies(tlsdata
);
2699 leave_apartment(tlsdata
);
2702 * Decrease the reference count.
2703 * If we are back to 0 locks on the COM library, make sure we free
2704 * all the associated data structures.
2706 lockcount
= InterlockedExchangeAdd(&com_lockcount
, -1);
2709 TRACE("Releasing the COM libraries\n");
2711 com_revoke_all_ps_clsids();
2712 DestroyRunningObjectTable();
2714 else if (lockcount
< 1)
2716 ERR("Unbalanced lock count %d\n", lockcount
);
2717 InterlockedExchangeAdd(&com_lockcount
, 1);
2720 lock_init_spies(tlsdata
);
2721 LIST_FOR_EACH_ENTRY(cursor
, &tlsdata
->spies
, struct init_spy
, entry
)
2723 if (cursor
->spy
) IInitializeSpy_PostUninitialize(cursor
->spy
, tlsdata
->inits
);
2725 unlock_init_spies(tlsdata
);
2728 /***********************************************************************
2729 * CoIncrementMTAUsage (combase.@)
2731 HRESULT WINAPI
CoIncrementMTAUsage(CO_MTA_USAGE_COOKIE
*cookie
)
2733 TRACE("%p\n", cookie
);
2735 return apartment_increment_mta_usage(cookie
);
2738 /***********************************************************************
2739 * CoDecrementMTAUsage (combase.@)
2741 HRESULT WINAPI
CoDecrementMTAUsage(CO_MTA_USAGE_COOKIE cookie
)
2743 TRACE("%p\n", cookie
);
2745 apartment_decrement_mta_usage(cookie
);
2749 /***********************************************************************
2750 * CoGetApartmentType (combase.@)
2752 HRESULT WINAPI
CoGetApartmentType(APTTYPE
*type
, APTTYPEQUALIFIER
*qualifier
)
2754 struct tlsdata
*tlsdata
;
2755 struct apartment
*apt
;
2758 TRACE("%p, %p\n", type
, qualifier
);
2760 if (!type
|| !qualifier
)
2761 return E_INVALIDARG
;
2763 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
2767 *type
= APTTYPE_CURRENT
;
2768 else if (tlsdata
->apt
->multi_threaded
)
2769 *type
= APTTYPE_MTA
;
2770 else if (tlsdata
->apt
->main
)
2771 *type
= APTTYPE_MAINSTA
;
2773 *type
= APTTYPE_STA
;
2775 *qualifier
= APTTYPEQUALIFIER_NONE
;
2777 if (!tlsdata
->apt
&& (apt
= apartment_get_mta()))
2779 apartment_release(apt
);
2780 *type
= APTTYPE_MTA
;
2781 *qualifier
= APTTYPEQUALIFIER_IMPLICIT_MTA
;
2785 return tlsdata
->apt
? S_OK
: CO_E_NOTINITIALIZED
;
2788 /******************************************************************************
2789 * CoRegisterClassObject (combase.@)
2791 * MSDN claims that multiple interface registrations are legal, but we
2792 * can't do that with our current implementation.
2794 HRESULT WINAPI
CoRegisterClassObject(REFCLSID rclsid
, IUnknown
*object
, DWORD clscontext
,
2795 DWORD flags
, DWORD
*cookie
)
2797 static LONG next_cookie
;
2799 struct registered_class
*newclass
;
2800 IUnknown
*found_object
;
2801 struct apartment
*apt
;
2804 TRACE("%s, %p, %#x, %#x, %p\n", debugstr_guid(rclsid
), object
, clscontext
, flags
, cookie
);
2806 if (!cookie
|| !object
)
2807 return E_INVALIDARG
;
2809 if (!(apt
= apartment_get_current_or_mta()))
2811 ERR("COM was not initialized\n");
2812 return CO_E_NOTINITIALIZED
;
2817 /* REGCLS_MULTIPLEUSE implies registering as inproc server. This is what
2818 * differentiates the flag from REGCLS_MULTI_SEPARATE. */
2819 if (flags
& REGCLS_MULTIPLEUSE
)
2820 clscontext
|= CLSCTX_INPROC_SERVER
;
2823 * First, check if the class is already registered.
2824 * If it is, this should cause an error.
2826 if ((found_object
= com_get_registered_class_object(apt
, rclsid
, clscontext
)))
2828 if (flags
& REGCLS_MULTIPLEUSE
)
2830 if (clscontext
& CLSCTX_LOCAL_SERVER
)
2831 hr
= CoLockObjectExternal(found_object
, TRUE
, FALSE
);
2832 IUnknown_Release(found_object
);
2833 apartment_release(apt
);
2837 IUnknown_Release(found_object
);
2838 ERR("object already registered for class %s\n", debugstr_guid(rclsid
));
2839 apartment_release(apt
);
2840 return CO_E_OBJISREG
;
2843 newclass
= heap_alloc_zero(sizeof(*newclass
));
2846 apartment_release(apt
);
2847 return E_OUTOFMEMORY
;
2850 newclass
->clsid
= *rclsid
;
2851 newclass
->apartment_id
= apt
->oxid
;
2852 newclass
->clscontext
= clscontext
;
2853 newclass
->flags
= flags
;
2855 if (!(newclass
->cookie
= InterlockedIncrement(&next_cookie
)))
2856 newclass
->cookie
= InterlockedIncrement(&next_cookie
);
2858 newclass
->object
= object
;
2859 IUnknown_AddRef(newclass
->object
);
2861 EnterCriticalSection(®istered_classes_cs
);
2862 list_add_tail(®istered_classes
, &newclass
->entry
);
2863 LeaveCriticalSection(®istered_classes_cs
);
2865 *cookie
= newclass
->cookie
;
2867 if (clscontext
& CLSCTX_LOCAL_SERVER
)
2869 IStream
*marshal_stream
;
2871 hr
= apartment_get_local_server_stream(apt
, &marshal_stream
);
2874 apartment_release(apt
);
2878 hr
= rpc_register_local_server(&newclass
->clsid
, marshal_stream
, flags
, &newclass
->rpcss_cookie
);
2879 IStream_Release(marshal_stream
);
2882 apartment_release(apt
);
2886 static void com_revoke_class_object(struct registered_class
*entry
)
2888 list_remove(&entry
->entry
);
2890 if (entry
->clscontext
& CLSCTX_LOCAL_SERVER
)
2891 rpc_revoke_local_server(entry
->rpcss_cookie
);
2893 IUnknown_Release(entry
->object
);
2897 /* Cleans up rpcss registry */
2898 static void com_revoke_local_servers(void)
2900 struct registered_class
*cur
, *cur2
;
2902 EnterCriticalSection(®istered_classes_cs
);
2904 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, ®istered_classes
, struct registered_class
, entry
)
2906 if (cur
->clscontext
& CLSCTX_LOCAL_SERVER
)
2907 com_revoke_class_object(cur
);
2910 LeaveCriticalSection(®istered_classes_cs
);
2913 void apartment_revoke_all_classes(const struct apartment
*apt
)
2915 struct registered_class
*cur
, *cur2
;
2917 EnterCriticalSection(®istered_classes_cs
);
2919 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, ®istered_classes
, struct registered_class
, entry
)
2921 if (cur
->apartment_id
== apt
->oxid
)
2922 com_revoke_class_object(cur
);
2925 LeaveCriticalSection(®istered_classes_cs
);
2928 /***********************************************************************
2929 * CoRevokeClassObject (combase.@)
2931 HRESULT WINAPI DECLSPEC_HOTPATCH
CoRevokeClassObject(DWORD cookie
)
2933 HRESULT hr
= E_INVALIDARG
;
2934 struct registered_class
*cur
;
2935 struct apartment
*apt
;
2937 TRACE("%#x\n", cookie
);
2939 if (!(apt
= apartment_get_current_or_mta()))
2941 ERR("COM was not initialized\n");
2942 return CO_E_NOTINITIALIZED
;
2945 EnterCriticalSection(®istered_classes_cs
);
2947 LIST_FOR_EACH_ENTRY(cur
, ®istered_classes
, struct registered_class
, entry
)
2949 if (cur
->cookie
!= cookie
)
2952 if (cur
->apartment_id
== apt
->oxid
)
2954 com_revoke_class_object(cur
);
2959 ERR("called from wrong apartment, should be called from %s\n", wine_dbgstr_longlong(cur
->apartment_id
));
2960 hr
= RPC_E_WRONG_THREAD
;
2966 LeaveCriticalSection(®istered_classes_cs
);
2967 apartment_release(apt
);
2972 /***********************************************************************
2973 * CoAddRefServerProcess (combase.@)
2975 ULONG WINAPI
CoAddRefServerProcess(void)
2981 EnterCriticalSection(®istered_classes_cs
);
2982 refs
= ++com_server_process_refcount
;
2983 LeaveCriticalSection(®istered_classes_cs
);
2985 TRACE("refs before: %d\n", refs
- 1);
2990 /***********************************************************************
2991 * CoReleaseServerProcess [OLE32.@]
2993 ULONG WINAPI
CoReleaseServerProcess(void)
2999 EnterCriticalSection(®istered_classes_cs
);
3001 refs
= --com_server_process_refcount
;
3002 /* FIXME: suspend objects */
3004 LeaveCriticalSection(®istered_classes_cs
);
3006 TRACE("refs after: %d\n", refs
);
3011 /******************************************************************************
3012 * CoDisconnectObject (combase.@)
3014 HRESULT WINAPI
CoDisconnectObject(IUnknown
*object
, DWORD reserved
)
3016 struct stub_manager
*manager
;
3017 struct apartment
*apt
;
3021 TRACE("%p, %#x\n", object
, reserved
);
3024 return E_INVALIDARG
;
3026 hr
= IUnknown_QueryInterface(object
, &IID_IMarshal
, (void **)&marshal
);
3029 hr
= IMarshal_DisconnectObject(marshal
, reserved
);
3030 IMarshal_Release(marshal
);
3034 if (!(apt
= apartment_get_current_or_mta()))
3036 ERR("apartment not initialised\n");
3037 return CO_E_NOTINITIALIZED
;
3040 manager
= get_stub_manager_from_object(apt
, object
, FALSE
);
3043 stub_manager_disconnect(manager
);
3044 /* Release stub manager twice, to remove the apartment reference. */
3045 stub_manager_int_release(manager
);
3046 stub_manager_int_release(manager
);
3049 /* Note: native is pretty broken here because it just silently
3050 * fails, without returning an appropriate error code if the object was
3051 * not found, making apps think that the object was disconnected, when
3052 * it actually wasn't */
3054 apartment_release(apt
);
3058 /******************************************************************************
3059 * CoLockObjectExternal (combase.@)
3061 HRESULT WINAPI
CoLockObjectExternal(IUnknown
*object
, BOOL lock
, BOOL last_unlock_releases
)
3063 struct stub_manager
*stubmgr
;
3064 struct apartment
*apt
;
3066 TRACE("%p, %d, %d\n", object
, lock
, last_unlock_releases
);
3068 if (!(apt
= apartment_get_current_or_mta()))
3070 ERR("apartment not initialised\n");
3071 return CO_E_NOTINITIALIZED
;
3074 stubmgr
= get_stub_manager_from_object(apt
, object
, lock
);
3077 WARN("stub object not found %p\n", object
);
3078 /* Note: native is pretty broken here because it just silently
3079 * fails, without returning an appropriate error code, making apps
3080 * think that the object was disconnected, when it actually wasn't */
3081 apartment_release(apt
);
3086 stub_manager_ext_addref(stubmgr
, 1, FALSE
);
3088 stub_manager_ext_release(stubmgr
, 1, FALSE
, last_unlock_releases
);
3090 stub_manager_int_release(stubmgr
);
3091 apartment_release(apt
);
3095 /***********************************************************************
3096 * CoRegisterChannelHook (combase.@)
3098 HRESULT WINAPI
CoRegisterChannelHook(REFGUID guidExtension
, IChannelHook
*channel_hook
)
3100 TRACE("%s, %p\n", debugstr_guid(guidExtension
), channel_hook
);
3102 return rpc_register_channel_hook(guidExtension
, channel_hook
);
3105 /***********************************************************************
3106 * CoDisableCallCancellation (combase.@)
3108 HRESULT WINAPI
CoDisableCallCancellation(void *reserved
)
3110 struct tlsdata
*tlsdata
;
3113 TRACE("%p\n", reserved
);
3115 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
3118 if (!tlsdata
->cancelcount
)
3119 return CO_E_CANCEL_DISABLED
;
3121 tlsdata
->cancelcount
--;
3126 /***********************************************************************
3127 * CoEnableCallCancellation (combase.@)
3129 HRESULT WINAPI
CoEnableCallCancellation(void *reserved
)
3131 struct tlsdata
*tlsdata
;
3134 TRACE("%p\n", reserved
);
3136 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
3139 tlsdata
->cancelcount
++;
3144 /***********************************************************************
3145 * CoGetCallerTID (combase.@)
3147 HRESULT WINAPI
CoGetCallerTID(DWORD
*tid
)
3153 /***********************************************************************
3154 * CoIsHandlerConnected (combase.@)
3156 BOOL WINAPI
CoIsHandlerConnected(IUnknown
*object
)
3158 FIXME("%p\n", object
);
3163 /***********************************************************************
3164 * CoSuspendClassObjects (combase.@)
3166 HRESULT WINAPI
CoSuspendClassObjects(void)
3173 /***********************************************************************
3174 * CoResumeClassObjects (combase.@)
3176 HRESULT WINAPI
CoResumeClassObjects(void)
3183 /***********************************************************************
3184 * CoRegisterSurrogate (combase.@)
3186 HRESULT WINAPI
CoRegisterSurrogate(ISurrogate
*surrogate
)
3188 FIXME("%p stub\n", surrogate
);
3193 /***********************************************************************
3194 * CoRegisterSurrogateEx (combase.@)
3196 HRESULT WINAPI
CoRegisterSurrogateEx(REFGUID guid
, void *reserved
)
3198 FIXME("%s, %p stub\n", debugstr_guid(guid
), reserved
);
3203 /***********************************************************************
3204 * DllMain (combase.@)
3206 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD reason
, LPVOID reserved
)
3208 TRACE("%p 0x%x %p\n", hinstDLL
, reason
, reserved
);
3212 case DLL_PROCESS_ATTACH
:
3213 hProxyDll
= hinstDLL
;
3215 case DLL_PROCESS_DETACH
:
3216 com_revoke_local_servers();
3217 if (reserved
) break;
3218 apartment_global_cleanup();
3219 DeleteCriticalSection(®istered_classes_cs
);
3220 rpc_unregister_channel_hooks();
3222 case DLL_THREAD_DETACH
:
3223 com_cleanup_tlsdata();