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
);
39 #define CHARS_IN_GUID 39
41 struct comclassredirect_data
57 DWORD miscstatuscontent
;
58 DWORD miscstatusthumbnail
;
60 DWORD miscstatusdocprint
;
63 struct ifacepsredirect_data
75 struct progidredirect_data
96 static struct list registered_proxystubs
= LIST_INIT(registered_proxystubs
);
98 static CRITICAL_SECTION cs_registered_ps
;
99 static CRITICAL_SECTION_DEBUG psclsid_cs_debug
=
101 0, 0, &cs_registered_ps
,
102 { &psclsid_cs_debug
.ProcessLocksList
, &psclsid_cs_debug
.ProcessLocksList
},
103 0, 0, { (DWORD_PTR
)(__FILE__
": cs_registered_psclsid_list") }
105 static CRITICAL_SECTION cs_registered_ps
= { &psclsid_cs_debug
, -1, 0, 0, 0, 0 };
107 extern BOOL WINAPI
InternalIsInitialized(void);
109 static struct init_spy
*get_spy_entry(struct tlsdata
*tlsdata
, unsigned int id
)
111 struct init_spy
*spy
;
113 LIST_FOR_EACH_ENTRY(spy
, &tlsdata
->spies
, struct init_spy
, entry
)
115 if (id
== spy
->id
&& spy
->spy
)
122 static NTSTATUS
create_key(HKEY
*retkey
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
)
124 NTSTATUS status
= NtCreateKey((HANDLE
*)retkey
, access
, attr
, 0, NULL
, 0, NULL
);
126 if (status
== STATUS_OBJECT_NAME_NOT_FOUND
)
128 HANDLE subkey
, root
= attr
->RootDirectory
;
129 WCHAR
*buffer
= attr
->ObjectName
->Buffer
;
130 DWORD attrs
, pos
= 0, i
= 0, len
= attr
->ObjectName
->Length
/ sizeof(WCHAR
);
133 while (i
< len
&& buffer
[i
] != '\\') i
++;
134 if (i
== len
) return status
;
136 attrs
= attr
->Attributes
;
137 attr
->ObjectName
= &str
;
141 str
.Buffer
= buffer
+ pos
;
142 str
.Length
= (i
- pos
) * sizeof(WCHAR
);
143 status
= NtCreateKey(&subkey
, access
, attr
, 0, NULL
, 0, NULL
);
144 if (attr
->RootDirectory
!= root
) NtClose(attr
->RootDirectory
);
145 if (status
) return status
;
146 attr
->RootDirectory
= subkey
;
147 while (i
< len
&& buffer
[i
] == '\\') i
++;
149 while (i
< len
&& buffer
[i
] != '\\') i
++;
151 str
.Buffer
= buffer
+ pos
;
152 str
.Length
= (i
- pos
) * sizeof(WCHAR
);
153 attr
->Attributes
= attrs
;
154 status
= NtCreateKey((HANDLE
*)retkey
, access
, attr
, 0, NULL
, 0, NULL
);
155 if (attr
->RootDirectory
!= root
) NtClose(attr
->RootDirectory
);
160 static HKEY classes_root_hkey
;
162 static HKEY
create_classes_root_hkey(DWORD access
)
165 OBJECT_ATTRIBUTES attr
;
168 attr
.Length
= sizeof(attr
);
169 attr
.RootDirectory
= 0;
170 attr
.ObjectName
= &name
;
172 attr
.SecurityDescriptor
= NULL
;
173 attr
.SecurityQualityOfService
= NULL
;
174 RtlInitUnicodeString(&name
, L
"\\Registry\\Machine\\Software\\Classes");
176 if (create_key( &hkey
, access
, &attr
)) return 0;
177 TRACE( "%s -> %p\n", debugstr_w(attr
.ObjectName
->Buffer
), hkey
);
179 if (!(access
& KEY_WOW64_64KEY
))
181 if (!(ret
= InterlockedCompareExchangePointer( (void **)&classes_root_hkey
, hkey
, 0 )))
184 NtClose( hkey
); /* somebody beat us to it */
191 static HKEY
get_classes_root_hkey(HKEY hkey
, REGSAM access
);
193 static LSTATUS
create_classes_key(HKEY hkey
, const WCHAR
*name
, REGSAM access
, HKEY
*retkey
)
195 OBJECT_ATTRIBUTES attr
;
196 UNICODE_STRING nameW
;
198 if (!(hkey
= get_classes_root_hkey(hkey
, access
)))
199 return ERROR_INVALID_HANDLE
;
201 attr
.Length
= sizeof(attr
);
202 attr
.RootDirectory
= hkey
;
203 attr
.ObjectName
= &nameW
;
205 attr
.SecurityDescriptor
= NULL
;
206 attr
.SecurityQualityOfService
= NULL
;
207 RtlInitUnicodeString( &nameW
, name
);
209 return RtlNtStatusToDosError(create_key(retkey
, access
, &attr
));
212 static HKEY
get_classes_root_hkey(HKEY hkey
, REGSAM access
)
215 const BOOL is_win64
= sizeof(void*) > sizeof(int);
216 const BOOL force_wow32
= is_win64
&& (access
& KEY_WOW64_32KEY
);
218 if (hkey
== HKEY_CLASSES_ROOT
&&
219 ((access
& KEY_WOW64_64KEY
) || !(ret
= classes_root_hkey
)))
220 ret
= create_classes_root_hkey(MAXIMUM_ALLOWED
| (access
& KEY_WOW64_64KEY
));
221 if (force_wow32
&& ret
&& ret
== classes_root_hkey
)
223 access
&= ~KEY_WOW64_32KEY
;
224 if (create_classes_key(classes_root_hkey
, L
"Wow6432Node", access
, &hkey
))
232 static LSTATUS
open_classes_key(HKEY hkey
, const WCHAR
*name
, REGSAM access
, HKEY
*retkey
)
234 OBJECT_ATTRIBUTES attr
;
235 UNICODE_STRING nameW
;
237 if (!(hkey
= get_classes_root_hkey(hkey
, access
)))
238 return ERROR_INVALID_HANDLE
;
240 attr
.Length
= sizeof(attr
);
241 attr
.RootDirectory
= hkey
;
242 attr
.ObjectName
= &nameW
;
244 attr
.SecurityDescriptor
= NULL
;
245 attr
.SecurityQualityOfService
= NULL
;
246 RtlInitUnicodeString( &nameW
, name
);
248 return RtlNtStatusToDosError(NtOpenKey((HANDLE
*)retkey
, access
, &attr
));
251 static HRESULT
open_key_for_clsid(REFCLSID clsid
, const WCHAR
*keyname
, REGSAM access
, HKEY
*subkey
)
253 static const WCHAR clsidW
[] = L
"CLSID\\";
254 WCHAR path
[CHARS_IN_GUID
+ ARRAY_SIZE(clsidW
) - 1];
258 lstrcpyW(path
, clsidW
);
259 StringFromGUID2(clsid
, path
+ lstrlenW(clsidW
), CHARS_IN_GUID
);
260 res
= open_classes_key(HKEY_CLASSES_ROOT
, path
, keyname
? KEY_READ
: access
, &key
);
261 if (res
== ERROR_FILE_NOT_FOUND
)
262 return REGDB_E_CLASSNOTREG
;
263 else if (res
!= ERROR_SUCCESS
)
264 return REGDB_E_READREGDB
;
272 res
= open_classes_key(key
, keyname
, access
, subkey
);
274 if (res
== ERROR_FILE_NOT_FOUND
)
275 return REGDB_E_KEYMISSING
;
276 else if (res
!= ERROR_SUCCESS
)
277 return REGDB_E_READREGDB
;
282 /***********************************************************************
283 * InternalTlsAllocData (combase.@)
285 HRESULT WINAPI
InternalTlsAllocData(struct tlsdata
**data
)
287 if (!(*data
= heap_alloc_zero(sizeof(**data
))))
288 return E_OUTOFMEMORY
;
290 list_init(&(*data
)->spies
);
291 NtCurrentTeb()->ReservedForOle
= *data
;
296 /***********************************************************************
297 * FreePropVariantArray (combase.@)
299 HRESULT WINAPI
FreePropVariantArray(ULONG count
, PROPVARIANT
*rgvars
)
303 TRACE("%u, %p.\n", count
, rgvars
);
308 for (i
= 0; i
< count
; ++i
)
309 PropVariantClear(&rgvars
[i
]);
314 static HRESULT
propvar_validatetype(VARTYPE vt
)
346 case VT_STREAMED_OBJECT
:
347 case VT_STORED_OBJECT
:
351 case VT_I1
|VT_VECTOR
:
352 case VT_I2
|VT_VECTOR
:
353 case VT_I4
|VT_VECTOR
:
354 case VT_I8
|VT_VECTOR
:
355 case VT_R4
|VT_VECTOR
:
356 case VT_R8
|VT_VECTOR
:
357 case VT_CY
|VT_VECTOR
:
358 case VT_DATE
|VT_VECTOR
:
359 case VT_BSTR
|VT_VECTOR
:
360 case VT_ERROR
|VT_VECTOR
:
361 case VT_BOOL
|VT_VECTOR
:
362 case VT_VARIANT
|VT_VECTOR
:
363 case VT_UI1
|VT_VECTOR
:
364 case VT_UI2
|VT_VECTOR
:
365 case VT_UI4
|VT_VECTOR
:
366 case VT_UI8
|VT_VECTOR
:
367 case VT_LPSTR
|VT_VECTOR
:
368 case VT_LPWSTR
|VT_VECTOR
:
369 case VT_FILETIME
|VT_VECTOR
:
370 case VT_CF
|VT_VECTOR
:
371 case VT_CLSID
|VT_VECTOR
:
373 case VT_ARRAY
|VT_UI1
:
375 case VT_ARRAY
|VT_UI2
:
377 case VT_ARRAY
|VT_UI4
:
378 case VT_ARRAY
|VT_INT
:
379 case VT_ARRAY
|VT_UINT
:
383 case VT_ARRAY
|VT_DATE
:
384 case VT_ARRAY
|VT_BSTR
:
385 case VT_ARRAY
|VT_BOOL
:
386 case VT_ARRAY
|VT_DECIMAL
:
387 case VT_ARRAY
|VT_DISPATCH
:
388 case VT_ARRAY
|VT_UNKNOWN
:
389 case VT_ARRAY
|VT_ERROR
:
390 case VT_ARRAY
|VT_VARIANT
:
393 WARN("Bad type %d\n", vt
);
394 return STG_E_INVALIDPARAMETER
;
397 static void propvar_free_cf_array(ULONG count
, CLIPDATA
*data
)
400 for (i
= 0; i
< count
; ++i
)
401 CoTaskMemFree(data
[i
].pClipData
);
404 /***********************************************************************
405 * PropVariantClear (combase.@)
407 HRESULT WINAPI
PropVariantClear(PROPVARIANT
*pvar
)
411 TRACE("%p.\n", pvar
);
416 hr
= propvar_validatetype(pvar
->vt
);
419 memset(pvar
, 0, sizeof(*pvar
));
449 case VT_STREAMED_OBJECT
:
451 case VT_STORED_OBJECT
:
453 IStream_Release(pvar
->u
.pStream
);
458 /* pick an arbitrary typed pointer - we don't care about the type
459 * as we are just freeing it */
460 CoTaskMemFree(pvar
->u
.puuid
);
464 CoTaskMemFree(pvar
->u
.blob
.pBlobData
);
467 SysFreeString(pvar
->u
.bstrVal
);
470 if (pvar
->u
.pclipdata
)
472 propvar_free_cf_array(1, pvar
->u
.pclipdata
);
473 CoTaskMemFree(pvar
->u
.pclipdata
);
477 if (pvar
->vt
& VT_VECTOR
)
481 switch (pvar
->vt
& ~VT_VECTOR
)
484 FreePropVariantArray(pvar
->u
.capropvar
.cElems
, pvar
->u
.capropvar
.pElems
);
487 propvar_free_cf_array(pvar
->u
.caclipdata
.cElems
, pvar
->u
.caclipdata
.pElems
);
490 for (i
= 0; i
< pvar
->u
.cabstr
.cElems
; i
++)
491 SysFreeString(pvar
->u
.cabstr
.pElems
[i
]);
494 for (i
= 0; i
< pvar
->u
.calpstr
.cElems
; i
++)
495 CoTaskMemFree(pvar
->u
.calpstr
.pElems
[i
]);
498 for (i
= 0; i
< pvar
->u
.calpwstr
.cElems
; i
++)
499 CoTaskMemFree(pvar
->u
.calpwstr
.pElems
[i
]);
502 if (pvar
->vt
& ~VT_VECTOR
)
504 /* pick an arbitrary VT_VECTOR structure - they all have the same
506 CoTaskMemFree(pvar
->u
.capropvar
.pElems
);
509 else if (pvar
->vt
& VT_ARRAY
)
510 hr
= SafeArrayDestroy(pvar
->u
.parray
);
513 WARN("Invalid/unsupported type %d\n", pvar
->vt
);
514 hr
= STG_E_INVALIDPARAMETER
;
518 memset(pvar
, 0, sizeof(*pvar
));
522 /***********************************************************************
523 * PropVariantCopy (combase.@)
525 HRESULT WINAPI
PropVariantCopy(PROPVARIANT
*pvarDest
, const PROPVARIANT
*pvarSrc
)
530 TRACE("%p, %p vt %04x.\n", pvarDest
, pvarSrc
, pvarSrc
->vt
);
532 hr
= propvar_validatetype(pvarSrc
->vt
);
534 return DISP_E_BADVARTYPE
;
536 /* this will deal with most cases */
537 *pvarDest
= *pvarSrc
;
565 case VT_STREAMED_OBJECT
:
567 case VT_STORED_OBJECT
:
568 if (pvarDest
->u
.pStream
)
569 IStream_AddRef(pvarDest
->u
.pStream
);
572 pvarDest
->u
.puuid
= CoTaskMemAlloc(sizeof(CLSID
));
573 *pvarDest
->u
.puuid
= *pvarSrc
->u
.puuid
;
576 if (pvarSrc
->u
.pszVal
)
578 len
= strlen(pvarSrc
->u
.pszVal
);
579 pvarDest
->u
.pszVal
= CoTaskMemAlloc((len
+1)*sizeof(CHAR
));
580 CopyMemory(pvarDest
->u
.pszVal
, pvarSrc
->u
.pszVal
, (len
+1)*sizeof(CHAR
));
584 if (pvarSrc
->u
.pwszVal
)
586 len
= lstrlenW(pvarSrc
->u
.pwszVal
);
587 pvarDest
->u
.pwszVal
= CoTaskMemAlloc((len
+1)*sizeof(WCHAR
));
588 CopyMemory(pvarDest
->u
.pwszVal
, pvarSrc
->u
.pwszVal
, (len
+1)*sizeof(WCHAR
));
593 if (pvarSrc
->u
.blob
.pBlobData
)
595 len
= pvarSrc
->u
.blob
.cbSize
;
596 pvarDest
->u
.blob
.pBlobData
= CoTaskMemAlloc(len
);
597 CopyMemory(pvarDest
->u
.blob
.pBlobData
, pvarSrc
->u
.blob
.pBlobData
, len
);
601 pvarDest
->u
.bstrVal
= SysAllocString(pvarSrc
->u
.bstrVal
);
604 if (pvarSrc
->u
.pclipdata
)
606 len
= pvarSrc
->u
.pclipdata
->cbSize
- sizeof(pvarSrc
->u
.pclipdata
->ulClipFmt
);
607 pvarDest
->u
.pclipdata
= CoTaskMemAlloc(sizeof (CLIPDATA
));
608 pvarDest
->u
.pclipdata
->cbSize
= pvarSrc
->u
.pclipdata
->cbSize
;
609 pvarDest
->u
.pclipdata
->ulClipFmt
= pvarSrc
->u
.pclipdata
->ulClipFmt
;
610 pvarDest
->u
.pclipdata
->pClipData
= CoTaskMemAlloc(len
);
611 CopyMemory(pvarDest
->u
.pclipdata
->pClipData
, pvarSrc
->u
.pclipdata
->pClipData
, len
);
615 if (pvarSrc
->vt
& VT_VECTOR
)
620 switch (pvarSrc
->vt
& ~VT_VECTOR
)
622 case VT_I1
: elemSize
= sizeof(pvarSrc
->u
.cVal
); break;
623 case VT_UI1
: elemSize
= sizeof(pvarSrc
->u
.bVal
); break;
624 case VT_I2
: elemSize
= sizeof(pvarSrc
->u
.iVal
); break;
625 case VT_UI2
: elemSize
= sizeof(pvarSrc
->u
.uiVal
); break;
626 case VT_BOOL
: elemSize
= sizeof(pvarSrc
->u
.boolVal
); break;
627 case VT_I4
: elemSize
= sizeof(pvarSrc
->u
.lVal
); break;
628 case VT_UI4
: elemSize
= sizeof(pvarSrc
->u
.ulVal
); break;
629 case VT_R4
: elemSize
= sizeof(pvarSrc
->u
.fltVal
); break;
630 case VT_R8
: elemSize
= sizeof(pvarSrc
->u
.dblVal
); break;
631 case VT_ERROR
: elemSize
= sizeof(pvarSrc
->u
.scode
); break;
632 case VT_I8
: elemSize
= sizeof(pvarSrc
->u
.hVal
); break;
633 case VT_UI8
: elemSize
= sizeof(pvarSrc
->u
.uhVal
); break;
634 case VT_CY
: elemSize
= sizeof(pvarSrc
->u
.cyVal
); break;
635 case VT_DATE
: elemSize
= sizeof(pvarSrc
->u
.date
); break;
636 case VT_FILETIME
: elemSize
= sizeof(pvarSrc
->u
.filetime
); break;
637 case VT_CLSID
: elemSize
= sizeof(*pvarSrc
->u
.puuid
); break;
638 case VT_CF
: elemSize
= sizeof(*pvarSrc
->u
.pclipdata
); break;
639 case VT_BSTR
: elemSize
= sizeof(pvarSrc
->u
.bstrVal
); break;
640 case VT_LPSTR
: elemSize
= sizeof(pvarSrc
->u
.pszVal
); break;
641 case VT_LPWSTR
: elemSize
= sizeof(pvarSrc
->u
.pwszVal
); break;
642 case VT_VARIANT
: elemSize
= sizeof(*pvarSrc
->u
.pvarVal
); break;
645 FIXME("Invalid element type: %ul\n", pvarSrc
->vt
& ~VT_VECTOR
);
648 len
= pvarSrc
->u
.capropvar
.cElems
;
649 pvarDest
->u
.capropvar
.pElems
= len
? CoTaskMemAlloc(len
* elemSize
) : NULL
;
650 if (pvarSrc
->vt
== (VT_VECTOR
| VT_VARIANT
))
652 for (i
= 0; i
< len
; i
++)
653 PropVariantCopy(&pvarDest
->u
.capropvar
.pElems
[i
], &pvarSrc
->u
.capropvar
.pElems
[i
]);
655 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_CF
))
657 FIXME("Copy clipformats\n");
659 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_BSTR
))
661 for (i
= 0; i
< len
; i
++)
662 pvarDest
->u
.cabstr
.pElems
[i
] = SysAllocString(pvarSrc
->u
.cabstr
.pElems
[i
]);
664 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_LPSTR
))
667 for (i
= 0; i
< len
; i
++)
669 strLen
= lstrlenA(pvarSrc
->u
.calpstr
.pElems
[i
]) + 1;
670 pvarDest
->u
.calpstr
.pElems
[i
] = CoTaskMemAlloc(strLen
);
671 memcpy(pvarDest
->u
.calpstr
.pElems
[i
],
672 pvarSrc
->u
.calpstr
.pElems
[i
], strLen
);
675 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_LPWSTR
))
678 for (i
= 0; i
< len
; i
++)
680 strLen
= (lstrlenW(pvarSrc
->u
.calpwstr
.pElems
[i
]) + 1) *
682 pvarDest
->u
.calpstr
.pElems
[i
] = CoTaskMemAlloc(strLen
);
683 memcpy(pvarDest
->u
.calpstr
.pElems
[i
],
684 pvarSrc
->u
.calpstr
.pElems
[i
], strLen
);
688 CopyMemory(pvarDest
->u
.capropvar
.pElems
, pvarSrc
->u
.capropvar
.pElems
, len
* elemSize
);
690 else if (pvarSrc
->vt
& VT_ARRAY
)
692 pvarDest
->u
.uhVal
.QuadPart
= 0;
693 return SafeArrayCopy(pvarSrc
->u
.parray
, &pvarDest
->u
.parray
);
696 WARN("Invalid/unsupported type %d\n", pvarSrc
->vt
);
702 /***********************************************************************
703 * CoFileTimeNow (combase.@)
705 HRESULT WINAPI
CoFileTimeNow(FILETIME
*filetime
)
707 GetSystemTimeAsFileTime(filetime
);
711 /******************************************************************************
712 * CoCreateGuid (combase.@)
714 HRESULT WINAPI
CoCreateGuid(GUID
*guid
)
718 if (!guid
) return E_INVALIDARG
;
720 status
= UuidCreate(guid
);
721 if (status
== RPC_S_OK
|| status
== RPC_S_UUID_LOCAL_ONLY
) return S_OK
;
722 return HRESULT_FROM_WIN32(status
);
725 /******************************************************************************
726 * CoQueryProxyBlanket (combase.@)
728 HRESULT WINAPI
CoQueryProxyBlanket(IUnknown
*proxy
, DWORD
*authn_service
,
729 DWORD
*authz_service
, OLECHAR
**servername
, DWORD
*authn_level
,
730 DWORD
*imp_level
, void **auth_info
, DWORD
*capabilities
)
732 IClientSecurity
*client_security
;
735 TRACE("%p, %p, %p, %p, %p, %p, %p, %p.\n", proxy
, authn_service
, authz_service
, servername
, authn_level
, imp_level
,
736 auth_info
, capabilities
);
738 hr
= IUnknown_QueryInterface(proxy
, &IID_IClientSecurity
, (void **)&client_security
);
741 hr
= IClientSecurity_QueryBlanket(client_security
, proxy
, authn_service
, authz_service
, servername
,
742 authn_level
, imp_level
, auth_info
, capabilities
);
743 IClientSecurity_Release(client_security
);
746 if (FAILED(hr
)) ERR("-- failed with %#x.\n", hr
);
750 /******************************************************************************
751 * CoSetProxyBlanket (combase.@)
753 HRESULT WINAPI
CoSetProxyBlanket(IUnknown
*proxy
, DWORD authn_service
, DWORD authz_service
,
754 OLECHAR
*servername
, DWORD authn_level
, DWORD imp_level
, void *auth_info
, DWORD capabilities
)
756 IClientSecurity
*client_security
;
759 TRACE("%p, %u, %u, %p, %u, %u, %p, %#x.\n", proxy
, authn_service
, authz_service
, servername
,
760 authn_level
, imp_level
, auth_info
, capabilities
);
762 hr
= IUnknown_QueryInterface(proxy
, &IID_IClientSecurity
, (void **)&client_security
);
765 hr
= IClientSecurity_SetBlanket(client_security
, proxy
, authn_service
, authz_service
, servername
, authn_level
,
766 imp_level
, auth_info
, capabilities
);
767 IClientSecurity_Release(client_security
);
770 if (FAILED(hr
)) ERR("-- failed with %#x.\n", hr
);
774 /***********************************************************************
775 * CoCopyProxy (combase.@)
777 HRESULT WINAPI
CoCopyProxy(IUnknown
*proxy
, IUnknown
**proxy_copy
)
779 IClientSecurity
*client_security
;
782 TRACE("%p, %p.\n", proxy
, proxy_copy
);
784 hr
= IUnknown_QueryInterface(proxy
, &IID_IClientSecurity
, (void **)&client_security
);
787 hr
= IClientSecurity_CopyProxy(client_security
, proxy
, proxy_copy
);
788 IClientSecurity_Release(client_security
);
791 if (FAILED(hr
)) ERR("-- failed with %#x.\n", hr
);
795 /***********************************************************************
796 * CoQueryClientBlanket (combase.@)
798 HRESULT WINAPI
CoQueryClientBlanket(DWORD
*authn_service
, DWORD
*authz_service
, OLECHAR
**servername
,
799 DWORD
*authn_level
, DWORD
*imp_level
, RPC_AUTHZ_HANDLE
*privs
, DWORD
*capabilities
)
801 IServerSecurity
*server_security
;
804 TRACE("%p, %p, %p, %p, %p, %p, %p.\n", authn_service
, authz_service
, servername
, authn_level
, imp_level
,
805 privs
, capabilities
);
807 hr
= CoGetCallContext(&IID_IServerSecurity
, (void **)&server_security
);
810 hr
= IServerSecurity_QueryBlanket(server_security
, authn_service
, authz_service
, servername
, authn_level
,
811 imp_level
, privs
, capabilities
);
812 IServerSecurity_Release(server_security
);
818 /***********************************************************************
819 * CoImpersonateClient (combase.@)
821 HRESULT WINAPI
CoImpersonateClient(void)
823 IServerSecurity
*server_security
;
828 hr
= CoGetCallContext(&IID_IServerSecurity
, (void **)&server_security
);
831 hr
= IServerSecurity_ImpersonateClient(server_security
);
832 IServerSecurity_Release(server_security
);
838 /***********************************************************************
839 * CoRevertToSelf (combase.@)
841 HRESULT WINAPI
CoRevertToSelf(void)
843 IServerSecurity
*server_security
;
848 hr
= CoGetCallContext(&IID_IServerSecurity
, (void **)&server_security
);
851 hr
= IServerSecurity_RevertToSelf(server_security
);
852 IServerSecurity_Release(server_security
);
858 /***********************************************************************
859 * CoInitializeSecurity (combase.@)
861 HRESULT WINAPI
CoInitializeSecurity(PSECURITY_DESCRIPTOR sd
, LONG cAuthSvc
,
862 SOLE_AUTHENTICATION_SERVICE
*asAuthSvc
, void *reserved1
, DWORD authn_level
,
863 DWORD imp_level
, void *reserved2
, DWORD capabilities
, void *reserved3
)
865 FIXME("%p, %d, %p, %p, %d, %d, %p, %d, %p stub\n", sd
, cAuthSvc
, asAuthSvc
, reserved1
, authn_level
,
866 imp_level
, reserved2
, capabilities
, reserved3
);
871 /***********************************************************************
872 * CoGetObjectContext (combase.@)
874 HRESULT WINAPI
CoGetObjectContext(REFIID riid
, void **ppv
)
876 IObjContext
*context
;
879 TRACE("%s, %p.\n", debugstr_guid(riid
), ppv
);
882 hr
= CoGetContextToken((ULONG_PTR
*)&context
);
886 return IObjContext_QueryInterface(context
, riid
, ppv
);
889 /***********************************************************************
890 * CoGetDefaultContext (combase.@)
892 HRESULT WINAPI
CoGetDefaultContext(APTTYPE type
, REFIID riid
, void **obj
)
894 FIXME("%d, %s, %p stub\n", type
, debugstr_guid(riid
), obj
);
896 return E_NOINTERFACE
;
899 /***********************************************************************
900 * CoGetCallState (combase.@)
902 HRESULT WINAPI
CoGetCallState(int arg1
, ULONG
*arg2
)
904 FIXME("%d, %p.\n", arg1
, arg2
);
909 /***********************************************************************
910 * CoGetActivationState (combase.@)
912 HRESULT WINAPI
CoGetActivationState(GUID guid
, DWORD arg2
, DWORD
*arg3
)
914 FIXME("%s, %x, %p.\n", debugstr_guid(&guid
), arg2
, arg3
);
919 /******************************************************************************
920 * CoGetTreatAsClass (combase.@)
922 HRESULT WINAPI
CoGetTreatAsClass(REFCLSID clsidOld
, CLSID
*clsidNew
)
924 WCHAR buffW
[CHARS_IN_GUID
];
925 LONG len
= sizeof(buffW
);
929 TRACE("%s, %p.\n", debugstr_guid(clsidOld
), clsidNew
);
931 if (!clsidOld
|| !clsidNew
)
934 *clsidNew
= *clsidOld
;
936 hr
= open_key_for_clsid(clsidOld
, L
"TreatAs", KEY_READ
, &hkey
);
943 if (RegQueryValueW(hkey
, NULL
, buffW
, &len
))
949 hr
= CLSIDFromString(buffW
, clsidNew
);
951 ERR("Failed to get CLSID from string %s, hr %#x.\n", debugstr_w(buffW
), hr
);
953 if (hkey
) RegCloseKey(hkey
);
957 /******************************************************************************
958 * ProgIDFromCLSID (combase.@)
960 HRESULT WINAPI DECLSPEC_HOTPATCH
ProgIDFromCLSID(REFCLSID clsid
, LPOLESTR
*progid
)
962 ACTCTX_SECTION_KEYED_DATA data
;
972 data
.cbSize
= sizeof(data
);
973 if (FindActCtxSectionGuid(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
,
976 struct comclassredirect_data
*comclass
= (struct comclassredirect_data
*)data
.lpData
;
977 if (comclass
->progid_len
)
981 *progid
= CoTaskMemAlloc(comclass
->progid_len
+ sizeof(WCHAR
));
982 if (!*progid
) return E_OUTOFMEMORY
;
984 ptrW
= (WCHAR
*)((BYTE
*)comclass
+ comclass
->progid_offset
);
985 memcpy(*progid
, ptrW
, comclass
->progid_len
+ sizeof(WCHAR
));
989 return REGDB_E_CLASSNOTREG
;
992 hr
= open_key_for_clsid(clsid
, L
"ProgID", KEY_READ
, &hkey
);
996 if (RegQueryValueW(hkey
, NULL
, NULL
, &progidlen
))
997 hr
= REGDB_E_CLASSNOTREG
;
1001 *progid
= CoTaskMemAlloc(progidlen
* sizeof(WCHAR
));
1004 if (RegQueryValueW(hkey
, NULL
, *progid
, &progidlen
))
1006 hr
= REGDB_E_CLASSNOTREG
;
1007 CoTaskMemFree(*progid
);
1019 static inline BOOL
is_valid_hex(WCHAR c
)
1021 if (!(((c
>= '0') && (c
<= '9')) ||
1022 ((c
>= 'a') && (c
<= 'f')) ||
1023 ((c
>= 'A') && (c
<= 'F'))))
1028 static const BYTE guid_conv_table
[256] =
1030 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
1031 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
1032 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
1033 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
1034 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
1035 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
1036 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
1039 static BOOL
guid_from_string(LPCWSTR s
, GUID
*id
)
1043 if (!s
|| s
[0] != '{')
1045 memset(id
, 0, sizeof(*id
));
1046 if (!s
) return TRUE
;
1050 TRACE("%s -> %p\n", debugstr_w(s
), id
);
1052 /* In form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
1055 for (i
= 1; i
< 9; ++i
)
1057 if (!is_valid_hex(s
[i
])) return FALSE
;
1058 id
->Data1
= (id
->Data1
<< 4) | guid_conv_table
[s
[i
]];
1060 if (s
[9] != '-') return FALSE
;
1063 for (i
= 10; i
< 14; ++i
)
1065 if (!is_valid_hex(s
[i
])) return FALSE
;
1066 id
->Data2
= (id
->Data2
<< 4) | guid_conv_table
[s
[i
]];
1068 if (s
[14] != '-') return FALSE
;
1071 for (i
= 15; i
< 19; ++i
)
1073 if (!is_valid_hex(s
[i
])) return FALSE
;
1074 id
->Data3
= (id
->Data3
<< 4) | guid_conv_table
[s
[i
]];
1076 if (s
[19] != '-') return FALSE
;
1078 for (i
= 20; i
< 37; i
+= 2)
1082 if (s
[i
] != '-') return FALSE
;
1085 if (!is_valid_hex(s
[i
]) || !is_valid_hex(s
[i
+ 1])) return FALSE
;
1086 id
->Data4
[(i
- 20) / 2] = guid_conv_table
[s
[i
]] << 4 | guid_conv_table
[s
[i
+ 1]];
1089 if (s
[37] == '}' && s
[38] == '\0')
1095 static HRESULT
clsid_from_string_reg(LPCOLESTR progid
, CLSID
*clsid
)
1097 WCHAR buf2
[CHARS_IN_GUID
];
1098 LONG buf2len
= sizeof(buf2
);
1102 memset(clsid
, 0, sizeof(*clsid
));
1103 buf
= heap_alloc((lstrlenW(progid
) + 8) * sizeof(WCHAR
));
1104 if (!buf
) return E_OUTOFMEMORY
;
1106 lstrcpyW(buf
, progid
);
1107 lstrcatW(buf
, L
"\\CLSID");
1108 if (open_classes_key(HKEY_CLASSES_ROOT
, buf
, MAXIMUM_ALLOWED
, &xhkey
))
1111 WARN("couldn't open key for ProgID %s\n", debugstr_w(progid
));
1112 return CO_E_CLASSSTRING
;
1116 if (RegQueryValueW(xhkey
, NULL
, buf2
, &buf2len
))
1119 WARN("couldn't query clsid value for ProgID %s\n", debugstr_w(progid
));
1120 return CO_E_CLASSSTRING
;
1123 return guid_from_string(buf2
, clsid
) ? S_OK
: CO_E_CLASSSTRING
;
1126 /******************************************************************************
1127 * CLSIDFromProgID (combase.@)
1129 HRESULT WINAPI DECLSPEC_HOTPATCH
CLSIDFromProgID(LPCOLESTR progid
, CLSID
*clsid
)
1131 ACTCTX_SECTION_KEYED_DATA data
;
1133 if (!progid
|| !clsid
)
1134 return E_INVALIDARG
;
1136 data
.cbSize
= sizeof(data
);
1137 if (FindActCtxSectionStringW(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
,
1140 struct progidredirect_data
*progiddata
= (struct progidredirect_data
*)data
.lpData
;
1141 CLSID
*alias
= (CLSID
*)((BYTE
*)data
.lpSectionBase
+ progiddata
->clsid_offset
);
1146 return clsid_from_string_reg(progid
, clsid
);
1149 /******************************************************************************
1150 * CLSIDFromProgIDEx (combase.@)
1152 HRESULT WINAPI
CLSIDFromProgIDEx(LPCOLESTR progid
, CLSID
*clsid
)
1154 FIXME("%s, %p: semi-stub\n", debugstr_w(progid
), clsid
);
1156 return CLSIDFromProgID(progid
, clsid
);
1159 /******************************************************************************
1160 * CLSIDFromString (combase.@)
1162 HRESULT WINAPI
CLSIDFromString(LPCOLESTR str
, LPCLSID clsid
)
1168 return E_INVALIDARG
;
1170 if (guid_from_string(str
, clsid
))
1173 /* It appears a ProgID is also valid */
1174 hr
= clsid_from_string_reg(str
, &tmp_id
);
1181 /******************************************************************************
1182 * IIDFromString (combase.@)
1184 HRESULT WINAPI
IIDFromString(LPCOLESTR str
, IID
*iid
)
1186 TRACE("%s, %p\n", debugstr_w(str
), iid
);
1190 memset(iid
, 0, sizeof(*iid
));
1194 /* length mismatch is a special case */
1195 if (lstrlenW(str
) + 1 != CHARS_IN_GUID
)
1196 return E_INVALIDARG
;
1199 return CO_E_IIDSTRING
;
1201 return guid_from_string(str
, iid
) ? S_OK
: CO_E_IIDSTRING
;
1204 /******************************************************************************
1205 * StringFromCLSID (combase.@)
1207 HRESULT WINAPI
StringFromCLSID(REFCLSID clsid
, LPOLESTR
*str
)
1209 if (!(*str
= CoTaskMemAlloc(CHARS_IN_GUID
* sizeof(WCHAR
)))) return E_OUTOFMEMORY
;
1210 StringFromGUID2(clsid
, *str
, CHARS_IN_GUID
);
1214 /******************************************************************************
1215 * StringFromGUID2 (combase.@)
1217 INT WINAPI
StringFromGUID2(REFGUID guid
, LPOLESTR str
, INT cmax
)
1219 if (!guid
|| cmax
< CHARS_IN_GUID
) return 0;
1220 swprintf(str
, CHARS_IN_GUID
, L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", guid
->Data1
,
1221 guid
->Data2
, guid
->Data3
, guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
1222 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
1223 return CHARS_IN_GUID
;
1226 static void init_multi_qi(DWORD count
, MULTI_QI
*mqi
, HRESULT hr
)
1230 for (i
= 0; i
< count
; i
++)
1237 static HRESULT
return_multi_qi(IUnknown
*unk
, DWORD count
, MULTI_QI
*mqi
, BOOL include_unk
)
1239 ULONG index
= 0, fetched
= 0;
1245 index
= fetched
= 1;
1248 for (; index
< count
; index
++)
1250 mqi
[index
].hr
= IUnknown_QueryInterface(unk
, mqi
[index
].pIID
, (void **)&mqi
[index
].pItf
);
1251 if (mqi
[index
].hr
== S_OK
)
1256 IUnknown_Release(unk
);
1259 return E_NOINTERFACE
;
1261 return fetched
== count
? S_OK
: CO_S_NOTALLINTERFACES
;
1264 /***********************************************************************
1265 * CoGetInstanceFromFile (combase.@)
1267 HRESULT WINAPI DECLSPEC_HOTPATCH
CoGetInstanceFromFile(COSERVERINFO
*server_info
, CLSID
*rclsid
,
1268 IUnknown
*outer
, DWORD cls_context
, DWORD grfmode
, OLECHAR
*filename
, DWORD count
,
1271 IPersistFile
*pf
= NULL
;
1272 IUnknown
*obj
= NULL
;
1276 if (!count
|| !results
)
1277 return E_INVALIDARG
;
1280 FIXME("() non-NULL server_info not supported\n");
1282 init_multi_qi(count
, results
, E_NOINTERFACE
);
1286 hr
= GetClassFile(filename
, &clsid
);
1289 ERR("Failed to get CLSID from a file.\n");
1296 hr
= CoCreateInstance(rclsid
, outer
, cls_context
, &IID_IUnknown
, (void **)&obj
);
1299 init_multi_qi(count
, results
, hr
);
1303 /* Init from file */
1304 hr
= IUnknown_QueryInterface(obj
, &IID_IPersistFile
, (void **)&pf
);
1307 init_multi_qi(count
, results
, hr
);
1308 IUnknown_Release(obj
);
1312 hr
= IPersistFile_Load(pf
, filename
, grfmode
);
1313 IPersistFile_Release(pf
);
1315 return return_multi_qi(obj
, count
, results
, FALSE
);
1318 init_multi_qi(count
, results
, hr
);
1319 IUnknown_Release(obj
);
1324 /***********************************************************************
1325 * CoGetInstanceFromIStorage (combase.@)
1327 HRESULT WINAPI
CoGetInstanceFromIStorage(COSERVERINFO
*server_info
, CLSID
*rclsid
,
1328 IUnknown
*outer
, DWORD cls_context
, IStorage
*storage
, DWORD count
, MULTI_QI
*results
)
1330 IPersistStorage
*ps
= NULL
;
1331 IUnknown
*obj
= NULL
;
1335 if (!count
|| !results
|| !storage
)
1336 return E_INVALIDARG
;
1339 FIXME("() non-NULL server_info not supported\n");
1341 init_multi_qi(count
, results
, E_NOINTERFACE
);
1345 memset(&stat
.clsid
, 0, sizeof(stat
.clsid
));
1346 hr
= IStorage_Stat(storage
, &stat
, STATFLAG_NONAME
);
1349 ERR("Failed to get CLSID from a storage.\n");
1353 rclsid
= &stat
.clsid
;
1356 hr
= CoCreateInstance(rclsid
, outer
, cls_context
, &IID_IUnknown
, (void **)&obj
);
1360 /* Init from IStorage */
1361 hr
= IUnknown_QueryInterface(obj
, &IID_IPersistStorage
, (void **)&ps
);
1363 ERR("failed to get IPersistStorage\n");
1367 IPersistStorage_Load(ps
, storage
);
1368 IPersistStorage_Release(ps
);
1371 return return_multi_qi(obj
, count
, results
, FALSE
);
1374 /***********************************************************************
1375 * CoCreateInstance (combase.@)
1377 HRESULT WINAPI DECLSPEC_HOTPATCH
CoCreateInstance(REFCLSID rclsid
, IUnknown
*outer
, DWORD cls_context
,
1378 REFIID riid
, void **obj
)
1380 MULTI_QI multi_qi
= { .pIID
= riid
};
1383 TRACE("%s, %p, %#x, %s, %p.\n", debugstr_guid(rclsid
), outer
, cls_context
, debugstr_guid(riid
), obj
);
1388 hr
= CoCreateInstanceEx(rclsid
, outer
, cls_context
, NULL
, 1, &multi_qi
);
1389 *obj
= multi_qi
.pItf
;
1393 /***********************************************************************
1394 * CoCreateInstanceEx (combase.@)
1396 HRESULT WINAPI DECLSPEC_HOTPATCH
CoCreateInstanceEx(REFCLSID rclsid
, IUnknown
*outer
, DWORD cls_context
,
1397 COSERVERINFO
*server_info
, ULONG count
, MULTI_QI
*results
)
1399 IClassFactory
*factory
;
1400 IUnknown
*unk
= NULL
;
1404 TRACE("%s, %p, %#x, %p, %u, %p\n", debugstr_guid(rclsid
), outer
, cls_context
, server_info
, count
, results
);
1406 if (!count
|| !results
)
1407 return E_INVALIDARG
;
1410 FIXME("Server info is not supported.\n");
1412 init_multi_qi(count
, results
, E_NOINTERFACE
);
1414 hr
= CoGetTreatAsClass(rclsid
, &clsid
);
1418 hr
= CoGetClassObject(&clsid
, cls_context
, NULL
, &IID_IClassFactory
, (void **)&factory
);
1422 hr
= IClassFactory_CreateInstance(factory
, outer
, results
[0].pIID
, (void **)&unk
);
1423 IClassFactory_Release(factory
);
1426 if (hr
== CLASS_E_NOAGGREGATION
&& outer
)
1427 FIXME("Class %s does not support aggregation\n", debugstr_guid(&clsid
));
1429 FIXME("no instance created for interface %s of class %s, hr %#x.\n",
1430 debugstr_guid(results
[0].pIID
), debugstr_guid(&clsid
), hr
);
1434 return return_multi_qi(unk
, count
, results
, TRUE
);
1437 /***********************************************************************
1438 * CoFreeUnusedLibraries (combase.@)
1440 void WINAPI DECLSPEC_HOTPATCH
CoFreeUnusedLibraries(void)
1442 CoFreeUnusedLibrariesEx(INFINITE
, 0);
1445 /***********************************************************************
1446 * CoGetCallContext (combase.@)
1448 HRESULT WINAPI
CoGetCallContext(REFIID riid
, void **obj
)
1450 struct tlsdata
*tlsdata
;
1453 TRACE("%s, %p\n", debugstr_guid(riid
), obj
);
1455 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1458 if (!tlsdata
->call_state
)
1459 return RPC_E_CALL_COMPLETE
;
1461 return IUnknown_QueryInterface(tlsdata
->call_state
, riid
, obj
);
1464 /***********************************************************************
1465 * CoSwitchCallContext (combase.@)
1467 HRESULT WINAPI
CoSwitchCallContext(IUnknown
*context
, IUnknown
**old_context
)
1469 struct tlsdata
*tlsdata
;
1472 TRACE("%p, %p\n", context
, old_context
);
1474 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1477 /* Reference counts are not touched. */
1478 *old_context
= tlsdata
->call_state
;
1479 tlsdata
->call_state
= context
;
1484 /******************************************************************************
1485 * CoRegisterInitializeSpy (combase.@)
1487 HRESULT WINAPI
CoRegisterInitializeSpy(IInitializeSpy
*spy
, ULARGE_INTEGER
*cookie
)
1489 struct tlsdata
*tlsdata
;
1490 struct init_spy
*entry
;
1494 TRACE("%p, %p\n", spy
, cookie
);
1496 if (!spy
|| !cookie
)
1497 return E_INVALIDARG
;
1499 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1502 hr
= IInitializeSpy_QueryInterface(spy
, &IID_IInitializeSpy
, (void **)&spy
);
1506 entry
= heap_alloc(sizeof(*entry
));
1509 IInitializeSpy_Release(spy
);
1510 return E_OUTOFMEMORY
;
1516 while (get_spy_entry(tlsdata
, id
) != NULL
)
1522 list_add_head(&tlsdata
->spies
, &entry
->entry
);
1524 cookie
->u
.HighPart
= GetCurrentThreadId();
1525 cookie
->u
.LowPart
= entry
->id
;
1530 /******************************************************************************
1531 * CoRevokeInitializeSpy (combase.@)
1533 HRESULT WINAPI
CoRevokeInitializeSpy(ULARGE_INTEGER cookie
)
1535 struct tlsdata
*tlsdata
;
1536 struct init_spy
*spy
;
1539 TRACE("%s\n", wine_dbgstr_longlong(cookie
.QuadPart
));
1541 if (cookie
.u
.HighPart
!= GetCurrentThreadId())
1542 return E_INVALIDARG
;
1544 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1547 if (!(spy
= get_spy_entry(tlsdata
, cookie
.u
.LowPart
))) return E_INVALIDARG
;
1549 IInitializeSpy_Release(spy
->spy
);
1551 if (!tlsdata
->spies_lock
)
1553 list_remove(&spy
->entry
);
1559 static BOOL
com_peek_message(struct apartment
*apt
, MSG
*msg
)
1561 /* First try to retrieve messages for incoming COM calls to the apartment window */
1562 return (apt
->win
&& PeekMessageW(msg
, apt
->win
, 0, 0, PM_REMOVE
| PM_NOYIELD
)) ||
1563 /* Next retrieve other messages necessary for the app to remain responsive */
1564 PeekMessageW(msg
, NULL
, WM_DDE_FIRST
, WM_DDE_LAST
, PM_REMOVE
| PM_NOYIELD
) ||
1565 PeekMessageW(msg
, NULL
, 0, 0, PM_QS_PAINT
| PM_QS_SENDMESSAGE
| PM_REMOVE
| PM_NOYIELD
);
1568 /***********************************************************************
1569 * CoWaitForMultipleHandles (combase.@)
1571 HRESULT WINAPI
CoWaitForMultipleHandles(DWORD flags
, DWORD timeout
, ULONG handle_count
, HANDLE
*handles
,
1574 BOOL check_apc
= !!(flags
& COWAIT_ALERTABLE
), post_quit
= FALSE
, message_loop
;
1575 DWORD start_time
, wait_flags
= 0;
1576 struct tlsdata
*tlsdata
;
1577 struct apartment
*apt
;
1581 TRACE("%#x, %#x, %u, %p, %p\n", flags
, timeout
, handle_count
, handles
, index
);
1584 return E_INVALIDARG
;
1589 return E_INVALIDARG
;
1592 return RPC_E_NO_SYNC
;
1594 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
1597 apt
= com_get_current_apt();
1598 message_loop
= apt
&& !apt
->multi_threaded
;
1600 if (flags
& COWAIT_WAITALL
)
1601 wait_flags
|= MWMO_WAITALL
;
1602 if (flags
& COWAIT_ALERTABLE
)
1603 wait_flags
|= MWMO_ALERTABLE
;
1605 start_time
= GetTickCount();
1609 DWORD now
= GetTickCount(), res
;
1611 if (now
- start_time
> timeout
)
1613 hr
= RPC_S_CALLPENDING
;
1619 TRACE("waiting for rpc completion or window message\n");
1625 res
= WaitForMultipleObjectsEx(handle_count
, handles
, !!(flags
& COWAIT_WAITALL
), 0, TRUE
);
1629 if (res
== WAIT_TIMEOUT
)
1630 res
= MsgWaitForMultipleObjectsEx(handle_count
, handles
,
1631 timeout
== INFINITE
? INFINITE
: start_time
+ timeout
- now
,
1632 QS_SENDMESSAGE
| QS_ALLPOSTMESSAGE
| QS_PAINT
, wait_flags
);
1634 if (res
== WAIT_OBJECT_0
+ handle_count
) /* messages available */
1639 /* call message filter */
1643 PENDINGTYPE pendingtype
= tlsdata
->pending_call_count_server
? PENDINGTYPE_NESTED
: PENDINGTYPE_TOPLEVEL
;
1644 DWORD be_handled
= IMessageFilter_MessagePending(apt
->filter
, 0 /* FIXME */, now
- start_time
, pendingtype
);
1646 TRACE("IMessageFilter_MessagePending returned %d\n", be_handled
);
1650 case PENDINGMSG_CANCELCALL
:
1651 WARN("call canceled\n");
1652 hr
= RPC_E_CALL_CANCELED
;
1654 case PENDINGMSG_WAITNOPROCESS
:
1655 case PENDINGMSG_WAITDEFPROCESS
:
1657 /* FIXME: MSDN is very vague about the difference
1658 * between WAITNOPROCESS and WAITDEFPROCESS - there
1659 * appears to be none, so it is possibly a left-over
1660 * from the 16-bit world. */
1667 /* If window is NULL on apartment, peek at messages so that it will not trigger
1668 * MsgWaitForMultipleObjects next time. */
1669 PeekMessageW(NULL
, NULL
, 0, 0, PM_QS_POSTMESSAGE
| PM_NOREMOVE
| PM_NOYIELD
);
1672 /* Some apps (e.g. Visio 2010) don't handle WM_PAINT properly and loop forever,
1673 * so after processing 100 messages we go back to checking the wait handles */
1674 while (msg_count
++ < 100 && com_peek_message(apt
, &msg
))
1676 if (msg
.message
== WM_QUIT
)
1678 TRACE("Received WM_QUIT message\n");
1680 exit_code
= msg
.wParam
;
1684 TRACE("Received message whilst waiting for RPC: 0x%04x\n", msg
.message
);
1685 TranslateMessage(&msg
);
1686 DispatchMessageW(&msg
);
1694 TRACE("Waiting for rpc completion\n");
1696 res
= WaitForMultipleObjectsEx(handle_count
, handles
, !!(flags
& COWAIT_WAITALL
),
1697 (timeout
== INFINITE
) ? INFINITE
: start_time
+ timeout
- now
, !!(flags
& COWAIT_ALERTABLE
));
1703 hr
= RPC_S_CALLPENDING
;
1706 hr
= HRESULT_FROM_WIN32(GetLastError());
1714 if (post_quit
) PostQuitMessage(exit_code
);
1716 TRACE("-- 0x%08x\n", hr
);
1721 /******************************************************************************
1722 * CoRegisterMessageFilter (combase.@)
1724 HRESULT WINAPI
CoRegisterMessageFilter(IMessageFilter
*filter
, IMessageFilter
**ret_filter
)
1726 IMessageFilter
*old_filter
;
1727 struct apartment
*apt
;
1729 TRACE("%p, %p\n", filter
, ret_filter
);
1731 apt
= com_get_current_apt();
1733 /* Can't set a message filter in a multi-threaded apartment */
1734 if (!apt
|| apt
->multi_threaded
)
1736 WARN("Can't set message filter in MTA or uninitialized apt\n");
1737 return CO_E_NOT_SUPPORTED
;
1741 IMessageFilter_AddRef(filter
);
1743 EnterCriticalSection(&apt
->cs
);
1745 old_filter
= apt
->filter
;
1746 apt
->filter
= filter
;
1748 LeaveCriticalSection(&apt
->cs
);
1751 *ret_filter
= old_filter
;
1752 else if (old_filter
)
1753 IMessageFilter_Release(old_filter
);
1758 void WINAPI
InternalRevokeAllPSClsids(void)
1760 struct registered_ps
*cur
, *cur2
;
1762 EnterCriticalSection(&cs_registered_ps
);
1764 LIST_FOR_EACH_ENTRY_SAFE(cur
, cur2
, ®istered_proxystubs
, struct registered_ps
, entry
)
1766 list_remove(&cur
->entry
);
1770 LeaveCriticalSection(&cs_registered_ps
);
1773 static HRESULT
get_ps_clsid_from_registry(const WCHAR
* path
, REGSAM access
, CLSID
*pclsid
)
1775 WCHAR value
[CHARS_IN_GUID
];
1781 if (open_classes_key(HKEY_CLASSES_ROOT
, path
, access
, &hkey
))
1782 return REGDB_E_IIDNOTREG
;
1784 len
= sizeof(value
);
1785 if (ERROR_SUCCESS
!= RegQueryValueExW(hkey
, NULL
, NULL
, NULL
, (BYTE
*)value
, &len
))
1786 return REGDB_E_IIDNOTREG
;
1789 if (CLSIDFromString(value
, pclsid
) != NOERROR
)
1790 return REGDB_E_IIDNOTREG
;
1795 /*****************************************************************************
1796 * CoGetPSClsid (combase.@)
1798 HRESULT WINAPI
CoGetPSClsid(REFIID riid
, CLSID
*pclsid
)
1800 static const WCHAR interfaceW
[] = L
"Interface\\";
1801 static const WCHAR psW
[] = L
"\\ProxyStubClsid32";
1802 WCHAR path
[ARRAY_SIZE(interfaceW
) - 1 + CHARS_IN_GUID
- 1 + ARRAY_SIZE(psW
)];
1803 ACTCTX_SECTION_KEYED_DATA data
;
1804 struct registered_ps
*cur
;
1805 REGSAM opposite
= (sizeof(void*) > sizeof(int)) ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
;
1809 TRACE("%s, %p\n", debugstr_guid(riid
), pclsid
);
1811 if (!InternalIsInitialized())
1813 ERR("apartment not initialised\n");
1814 return CO_E_NOTINITIALIZED
;
1818 return E_INVALIDARG
;
1820 EnterCriticalSection(&cs_registered_ps
);
1822 LIST_FOR_EACH_ENTRY(cur
, ®istered_proxystubs
, struct registered_ps
, entry
)
1824 if (IsEqualIID(&cur
->iid
, riid
))
1826 *pclsid
= cur
->clsid
;
1827 LeaveCriticalSection(&cs_registered_ps
);
1832 LeaveCriticalSection(&cs_registered_ps
);
1834 data
.cbSize
= sizeof(data
);
1835 if (FindActCtxSectionGuid(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION
,
1838 struct ifacepsredirect_data
*ifaceps
= (struct ifacepsredirect_data
*)data
.lpData
;
1839 *pclsid
= ifaceps
->iid
;
1843 /* Interface\\{string form of riid}\\ProxyStubClsid32 */
1844 lstrcpyW(path
, interfaceW
);
1845 StringFromGUID2(riid
, path
+ ARRAY_SIZE(interfaceW
) - 1, CHARS_IN_GUID
);
1846 lstrcpyW(path
+ ARRAY_SIZE(interfaceW
) - 1 + CHARS_IN_GUID
- 1, psW
);
1848 hr
= get_ps_clsid_from_registry(path
, 0, pclsid
);
1849 if (FAILED(hr
) && (opposite
== KEY_WOW64_32KEY
|| (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)))
1850 hr
= get_ps_clsid_from_registry(path
, opposite
, pclsid
);
1853 TRACE("() Returning CLSID %s\n", debugstr_guid(pclsid
));
1855 WARN("No PSFactoryBuffer object is registered for IID %s\n", debugstr_guid(riid
));
1860 /*****************************************************************************
1861 * CoRegisterPSClsid (combase.@)
1863 HRESULT WINAPI
CoRegisterPSClsid(REFIID riid
, REFCLSID rclsid
)
1865 struct registered_ps
*cur
;
1867 TRACE("%s, %s\n", debugstr_guid(riid
), debugstr_guid(rclsid
));
1869 if (!InternalIsInitialized())
1871 ERR("apartment not initialised\n");
1872 return CO_E_NOTINITIALIZED
;
1875 EnterCriticalSection(&cs_registered_ps
);
1877 LIST_FOR_EACH_ENTRY(cur
, ®istered_proxystubs
, struct registered_ps
, entry
)
1879 if (IsEqualIID(&cur
->iid
, riid
))
1881 cur
->clsid
= *rclsid
;
1882 LeaveCriticalSection(&cs_registered_ps
);
1887 cur
= heap_alloc(sizeof(*cur
));
1890 LeaveCriticalSection(&cs_registered_ps
);
1891 return E_OUTOFMEMORY
;
1895 cur
->clsid
= *rclsid
;
1896 list_add_head(®istered_proxystubs
, &cur
->entry
);
1898 LeaveCriticalSection(&cs_registered_ps
);
1903 struct thread_context
1905 IComThreadingInfo IComThreadingInfo_iface
;
1906 IContextCallback IContextCallback_iface
;
1907 IObjContext IObjContext_iface
;
1911 static inline struct thread_context
*impl_from_IComThreadingInfo(IComThreadingInfo
*iface
)
1913 return CONTAINING_RECORD(iface
, struct thread_context
, IComThreadingInfo_iface
);
1916 static inline struct thread_context
*impl_from_IContextCallback(IContextCallback
*iface
)
1918 return CONTAINING_RECORD(iface
, struct thread_context
, IContextCallback_iface
);
1921 static inline struct thread_context
*impl_from_IObjContext(IObjContext
*iface
)
1923 return CONTAINING_RECORD(iface
, struct thread_context
, IObjContext_iface
);
1926 static HRESULT WINAPI
thread_context_info_QueryInterface(IComThreadingInfo
*iface
, REFIID riid
, void **obj
)
1928 struct thread_context
*context
= impl_from_IComThreadingInfo(iface
);
1932 if (IsEqualIID(riid
, &IID_IComThreadingInfo
) ||
1933 IsEqualIID(riid
, &IID_IUnknown
))
1935 *obj
= &context
->IComThreadingInfo_iface
;
1937 else if (IsEqualIID(riid
, &IID_IContextCallback
))
1939 *obj
= &context
->IContextCallback_iface
;
1941 else if (IsEqualIID(riid
, &IID_IObjContext
))
1943 *obj
= &context
->IObjContext_iface
;
1948 IUnknown_AddRef((IUnknown
*)*obj
);
1952 FIXME("interface not implemented %s\n", debugstr_guid(riid
));
1953 return E_NOINTERFACE
;
1956 static ULONG WINAPI
thread_context_info_AddRef(IComThreadingInfo
*iface
)
1958 struct thread_context
*context
= impl_from_IComThreadingInfo(iface
);
1959 return InterlockedIncrement(&context
->refcount
);
1962 static ULONG WINAPI
thread_context_info_Release(IComThreadingInfo
*iface
)
1964 struct thread_context
*context
= impl_from_IComThreadingInfo(iface
);
1966 /* Context instance is initially created with CoGetContextToken() with refcount set to 0,
1967 releasing context while refcount is at 0 destroys it. */
1968 if (!context
->refcount
)
1974 return InterlockedDecrement(&context
->refcount
);
1977 static HRESULT WINAPI
thread_context_info_GetCurrentApartmentType(IComThreadingInfo
*iface
, APTTYPE
*apttype
)
1979 APTTYPEQUALIFIER qualifier
;
1981 TRACE("%p\n", apttype
);
1983 return CoGetApartmentType(apttype
, &qualifier
);
1986 static HRESULT WINAPI
thread_context_info_GetCurrentThreadType(IComThreadingInfo
*iface
, THDTYPE
*thdtype
)
1988 APTTYPEQUALIFIER qualifier
;
1992 hr
= CoGetApartmentType(&apttype
, &qualifier
);
1996 TRACE("%p\n", thdtype
);
2001 case APTTYPE_MAINSTA
:
2002 *thdtype
= THDTYPE_PROCESSMESSAGES
;
2005 *thdtype
= THDTYPE_BLOCKMESSAGES
;
2011 static HRESULT WINAPI
thread_context_info_GetCurrentLogicalThreadId(IComThreadingInfo
*iface
, GUID
*logical_thread_id
)
2013 TRACE("%p\n", logical_thread_id
);
2015 return CoGetCurrentLogicalThreadId(logical_thread_id
);
2018 static HRESULT WINAPI
thread_context_info_SetCurrentLogicalThreadId(IComThreadingInfo
*iface
, REFGUID logical_thread_id
)
2020 FIXME("%s stub\n", debugstr_guid(logical_thread_id
));
2025 static const IComThreadingInfoVtbl thread_context_info_vtbl
=
2027 thread_context_info_QueryInterface
,
2028 thread_context_info_AddRef
,
2029 thread_context_info_Release
,
2030 thread_context_info_GetCurrentApartmentType
,
2031 thread_context_info_GetCurrentThreadType
,
2032 thread_context_info_GetCurrentLogicalThreadId
,
2033 thread_context_info_SetCurrentLogicalThreadId
2036 static HRESULT WINAPI
thread_context_callback_QueryInterface(IContextCallback
*iface
, REFIID riid
, void **obj
)
2038 struct thread_context
*context
= impl_from_IContextCallback(iface
);
2039 return IComThreadingInfo_QueryInterface(&context
->IComThreadingInfo_iface
, riid
, obj
);
2042 static ULONG WINAPI
thread_context_callback_AddRef(IContextCallback
*iface
)
2044 struct thread_context
*context
= impl_from_IContextCallback(iface
);
2045 return IComThreadingInfo_AddRef(&context
->IComThreadingInfo_iface
);
2048 static ULONG WINAPI
thread_context_callback_Release(IContextCallback
*iface
)
2050 struct thread_context
*context
= impl_from_IContextCallback(iface
);
2051 return IComThreadingInfo_Release(&context
->IComThreadingInfo_iface
);
2054 static HRESULT WINAPI
thread_context_callback_ContextCallback(IContextCallback
*iface
,
2055 PFNCONTEXTCALL callback
, ComCallData
*param
, REFIID riid
, int method
, IUnknown
*punk
)
2057 FIXME("%p, %p, %p, %s, %d, %p\n", iface
, callback
, param
, debugstr_guid(riid
), method
, punk
);
2062 static const IContextCallbackVtbl thread_context_callback_vtbl
=
2064 thread_context_callback_QueryInterface
,
2065 thread_context_callback_AddRef
,
2066 thread_context_callback_Release
,
2067 thread_context_callback_ContextCallback
2070 static HRESULT WINAPI
thread_object_context_QueryInterface(IObjContext
*iface
, REFIID riid
, void **obj
)
2072 struct thread_context
*context
= impl_from_IObjContext(iface
);
2073 return IComThreadingInfo_QueryInterface(&context
->IComThreadingInfo_iface
, riid
, obj
);
2076 static ULONG WINAPI
thread_object_context_AddRef(IObjContext
*iface
)
2078 struct thread_context
*context
= impl_from_IObjContext(iface
);
2079 return IComThreadingInfo_AddRef(&context
->IComThreadingInfo_iface
);
2082 static ULONG WINAPI
thread_object_context_Release(IObjContext
*iface
)
2084 struct thread_context
*context
= impl_from_IObjContext(iface
);
2085 return IComThreadingInfo_Release(&context
->IComThreadingInfo_iface
);
2088 static HRESULT WINAPI
thread_object_context_SetProperty(IObjContext
*iface
, REFGUID propid
, CPFLAGS flags
, IUnknown
*punk
)
2090 FIXME("%p, %s, %x, %p\n", iface
, debugstr_guid(propid
), flags
, punk
);
2095 static HRESULT WINAPI
thread_object_context_RemoveProperty(IObjContext
*iface
, REFGUID propid
)
2097 FIXME("%p, %s\n", iface
, debugstr_guid(propid
));
2102 static HRESULT WINAPI
thread_object_context_GetProperty(IObjContext
*iface
, REFGUID propid
, CPFLAGS
*flags
, IUnknown
**punk
)
2104 FIXME("%p, %s, %p, %p\n", iface
, debugstr_guid(propid
), flags
, punk
);
2109 static HRESULT WINAPI
thread_object_context_EnumContextProps(IObjContext
*iface
, IEnumContextProps
**props
)
2111 FIXME("%p, %p\n", iface
, props
);
2116 static void WINAPI
thread_object_context_Reserved1(IObjContext
*iface
)
2118 FIXME("%p\n", iface
);
2121 static void WINAPI
thread_object_context_Reserved2(IObjContext
*iface
)
2123 FIXME("%p\n", iface
);
2126 static void WINAPI
thread_object_context_Reserved3(IObjContext
*iface
)
2128 FIXME("%p\n", iface
);
2131 static void WINAPI
thread_object_context_Reserved4(IObjContext
*iface
)
2133 FIXME("%p\n", iface
);
2136 static void WINAPI
thread_object_context_Reserved5(IObjContext
*iface
)
2138 FIXME("%p\n", iface
);
2141 static void WINAPI
thread_object_context_Reserved6(IObjContext
*iface
)
2143 FIXME("%p\n", iface
);
2146 static void WINAPI
thread_object_context_Reserved7(IObjContext
*iface
)
2148 FIXME("%p\n", iface
);
2151 static const IObjContextVtbl thread_object_context_vtbl
=
2153 thread_object_context_QueryInterface
,
2154 thread_object_context_AddRef
,
2155 thread_object_context_Release
,
2156 thread_object_context_SetProperty
,
2157 thread_object_context_RemoveProperty
,
2158 thread_object_context_GetProperty
,
2159 thread_object_context_EnumContextProps
,
2160 thread_object_context_Reserved1
,
2161 thread_object_context_Reserved2
,
2162 thread_object_context_Reserved3
,
2163 thread_object_context_Reserved4
,
2164 thread_object_context_Reserved5
,
2165 thread_object_context_Reserved6
,
2166 thread_object_context_Reserved7
2169 /***********************************************************************
2170 * CoGetContextToken (combase.@)
2172 HRESULT WINAPI
CoGetContextToken(ULONG_PTR
*token
)
2174 struct tlsdata
*tlsdata
;
2177 TRACE("%p\n", token
);
2179 if (!InternalIsInitialized())
2181 ERR("apartment not initialised\n");
2182 return CO_E_NOTINITIALIZED
;
2185 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
2191 if (!tlsdata
->context_token
)
2193 struct thread_context
*context
;
2195 context
= heap_alloc_zero(sizeof(*context
));
2197 return E_OUTOFMEMORY
;
2199 context
->IComThreadingInfo_iface
.lpVtbl
= &thread_context_info_vtbl
;
2200 context
->IContextCallback_iface
.lpVtbl
= &thread_context_callback_vtbl
;
2201 context
->IObjContext_iface
.lpVtbl
= &thread_object_context_vtbl
;
2202 /* Context token does not take a reference, it's always zero until the
2203 interface is explicitly requested with CoGetObjectContext(). */
2204 context
->refcount
= 0;
2206 tlsdata
->context_token
= &context
->IObjContext_iface
;
2209 *token
= (ULONG_PTR
)tlsdata
->context_token
;
2210 TRACE("context_token %p\n", tlsdata
->context_token
);
2215 /***********************************************************************
2216 * CoGetCurrentLogicalThreadId (combase.@)
2218 HRESULT WINAPI
CoGetCurrentLogicalThreadId(GUID
*id
)
2220 struct tlsdata
*tlsdata
;
2224 return E_INVALIDARG
;
2226 if (FAILED(hr
= com_get_tlsdata(&tlsdata
)))
2229 if (IsEqualGUID(&tlsdata
->causality_id
, &GUID_NULL
))
2230 CoCreateGuid(&tlsdata
->causality_id
);
2232 *id
= tlsdata
->causality_id
;
2237 /******************************************************************************
2238 * CoGetCurrentProcess (combase.@)
2240 DWORD WINAPI
CoGetCurrentProcess(void)
2242 struct tlsdata
*tlsdata
;
2244 if (FAILED(com_get_tlsdata(&tlsdata
)))
2247 if (!tlsdata
->thread_seqid
)
2248 tlsdata
->thread_seqid
= rpcss_get_next_seqid();
2250 return tlsdata
->thread_seqid
;