combase: Move CoGetCurrentProcess().
[wine.git] / dlls / combase / combase.c
blobdf97799fe0845ae71fca7e87d445c31107fb5155
1 /*
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
20 #define COBJMACROS
21 #define NONAMELESSUNION
23 #include "ntstatus.h"
24 #define WIN32_NO_STATUS
25 #define USE_COM_CONTEXT_DEF
26 #include "objbase.h"
27 #include "ctxtcall.h"
28 #include "oleauto.h"
29 #include "dde.h"
30 #include "winternl.h"
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
43 ULONG size;
44 ULONG flags;
45 DWORD model;
46 GUID clsid;
47 GUID alias;
48 GUID clsid2;
49 GUID tlbid;
50 ULONG name_len;
51 ULONG name_offset;
52 ULONG progid_len;
53 ULONG progid_offset;
54 ULONG clrdata_len;
55 ULONG clrdata_offset;
56 DWORD miscstatus;
57 DWORD miscstatuscontent;
58 DWORD miscstatusthumbnail;
59 DWORD miscstatusicon;
60 DWORD miscstatusdocprint;
63 struct ifacepsredirect_data
65 ULONG size;
66 DWORD mask;
67 GUID iid;
68 ULONG nummethods;
69 GUID tlbid;
70 GUID base;
71 ULONG name_len;
72 ULONG name_offset;
75 struct progidredirect_data
77 ULONG size;
78 DWORD reserved;
79 ULONG clsid_offset;
82 struct init_spy
84 struct list entry;
85 IInitializeSpy *spy;
86 unsigned int id;
89 struct registered_ps
91 struct list entry;
92 IID iid;
93 CLSID clsid;
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)
116 return spy;
119 return NULL;
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);
131 UNICODE_STRING str;
133 while (i < len && buffer[i] != '\\') i++;
134 if (i == len) return status;
136 attrs = attr->Attributes;
137 attr->ObjectName = &str;
139 while (i < len)
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++;
148 pos = 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);
157 return status;
160 static HKEY classes_root_hkey;
162 static HKEY create_classes_root_hkey(DWORD access)
164 HKEY hkey, ret = 0;
165 OBJECT_ATTRIBUTES attr;
166 UNICODE_STRING name;
168 attr.Length = sizeof(attr);
169 attr.RootDirectory = 0;
170 attr.ObjectName = &name;
171 attr.Attributes = 0;
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 )))
182 ret = hkey;
183 else
184 NtClose( hkey ); /* somebody beat us to it */
186 else
187 ret = hkey;
188 return ret;
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;
204 attr.Attributes = 0;
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)
214 HKEY ret = hkey;
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))
225 return 0;
226 ret = hkey;
229 return ret;
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;
243 attr.Attributes = 0;
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];
255 LONG res;
256 HKEY key;
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;
266 if (!keyname)
268 *subkey = key;
269 return S_OK;
272 res = open_classes_key(key, keyname, access, subkey);
273 RegCloseKey(key);
274 if (res == ERROR_FILE_NOT_FOUND)
275 return REGDB_E_KEYMISSING;
276 else if (res != ERROR_SUCCESS)
277 return REGDB_E_READREGDB;
279 return S_OK;
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;
293 return S_OK;
296 /***********************************************************************
297 * FreePropVariantArray (combase.@)
299 HRESULT WINAPI FreePropVariantArray(ULONG count, PROPVARIANT *rgvars)
301 ULONG i;
303 TRACE("%u, %p.\n", count, rgvars);
305 if (!rgvars)
306 return E_INVALIDARG;
308 for (i = 0; i < count; ++i)
309 PropVariantClear(&rgvars[i]);
311 return S_OK;
314 static HRESULT propvar_validatetype(VARTYPE vt)
316 switch (vt)
318 case VT_EMPTY:
319 case VT_NULL:
320 case VT_I1:
321 case VT_I2:
322 case VT_I4:
323 case VT_I8:
324 case VT_R4:
325 case VT_R8:
326 case VT_CY:
327 case VT_DATE:
328 case VT_BSTR:
329 case VT_ERROR:
330 case VT_BOOL:
331 case VT_DECIMAL:
332 case VT_UI1:
333 case VT_UI2:
334 case VT_UI4:
335 case VT_UI8:
336 case VT_INT:
337 case VT_UINT:
338 case VT_LPSTR:
339 case VT_LPWSTR:
340 case VT_FILETIME:
341 case VT_BLOB:
342 case VT_DISPATCH:
343 case VT_UNKNOWN:
344 case VT_STREAM:
345 case VT_STORAGE:
346 case VT_STREAMED_OBJECT:
347 case VT_STORED_OBJECT:
348 case VT_BLOB_OBJECT:
349 case VT_CF:
350 case VT_CLSID:
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:
372 case VT_ARRAY|VT_I1:
373 case VT_ARRAY|VT_UI1:
374 case VT_ARRAY|VT_I2:
375 case VT_ARRAY|VT_UI2:
376 case VT_ARRAY|VT_I4:
377 case VT_ARRAY|VT_UI4:
378 case VT_ARRAY|VT_INT:
379 case VT_ARRAY|VT_UINT:
380 case VT_ARRAY|VT_R4:
381 case VT_ARRAY|VT_R8:
382 case VT_ARRAY|VT_CY:
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:
391 return S_OK;
393 WARN("Bad type %d\n", vt);
394 return STG_E_INVALIDPARAMETER;
397 static void propvar_free_cf_array(ULONG count, CLIPDATA *data)
399 ULONG i;
400 for (i = 0; i < count; ++i)
401 CoTaskMemFree(data[i].pClipData);
404 /***********************************************************************
405 * PropVariantClear (combase.@)
407 HRESULT WINAPI PropVariantClear(PROPVARIANT *pvar)
409 HRESULT hr;
411 TRACE("%p.\n", pvar);
413 if (!pvar)
414 return S_OK;
416 hr = propvar_validatetype(pvar->vt);
417 if (FAILED(hr))
419 memset(pvar, 0, sizeof(*pvar));
420 return hr;
423 switch (pvar->vt)
425 case VT_EMPTY:
426 case VT_NULL:
427 case VT_I1:
428 case VT_I2:
429 case VT_I4:
430 case VT_I8:
431 case VT_R4:
432 case VT_R8:
433 case VT_CY:
434 case VT_DATE:
435 case VT_ERROR:
436 case VT_BOOL:
437 case VT_DECIMAL:
438 case VT_UI1:
439 case VT_UI2:
440 case VT_UI4:
441 case VT_UI8:
442 case VT_INT:
443 case VT_UINT:
444 case VT_FILETIME:
445 break;
446 case VT_DISPATCH:
447 case VT_UNKNOWN:
448 case VT_STREAM:
449 case VT_STREAMED_OBJECT:
450 case VT_STORAGE:
451 case VT_STORED_OBJECT:
452 if (pvar->u.pStream)
453 IStream_Release(pvar->u.pStream);
454 break;
455 case VT_CLSID:
456 case VT_LPSTR:
457 case VT_LPWSTR:
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);
461 break;
462 case VT_BLOB:
463 case VT_BLOB_OBJECT:
464 CoTaskMemFree(pvar->u.blob.pBlobData);
465 break;
466 case VT_BSTR:
467 SysFreeString(pvar->u.bstrVal);
468 break;
469 case VT_CF:
470 if (pvar->u.pclipdata)
472 propvar_free_cf_array(1, pvar->u.pclipdata);
473 CoTaskMemFree(pvar->u.pclipdata);
475 break;
476 default:
477 if (pvar->vt & VT_VECTOR)
479 ULONG i;
481 switch (pvar->vt & ~VT_VECTOR)
483 case VT_VARIANT:
484 FreePropVariantArray(pvar->u.capropvar.cElems, pvar->u.capropvar.pElems);
485 break;
486 case VT_CF:
487 propvar_free_cf_array(pvar->u.caclipdata.cElems, pvar->u.caclipdata.pElems);
488 break;
489 case VT_BSTR:
490 for (i = 0; i < pvar->u.cabstr.cElems; i++)
491 SysFreeString(pvar->u.cabstr.pElems[i]);
492 break;
493 case VT_LPSTR:
494 for (i = 0; i < pvar->u.calpstr.cElems; i++)
495 CoTaskMemFree(pvar->u.calpstr.pElems[i]);
496 break;
497 case VT_LPWSTR:
498 for (i = 0; i < pvar->u.calpwstr.cElems; i++)
499 CoTaskMemFree(pvar->u.calpwstr.pElems[i]);
500 break;
502 if (pvar->vt & ~VT_VECTOR)
504 /* pick an arbitrary VT_VECTOR structure - they all have the same
505 * memory layout */
506 CoTaskMemFree(pvar->u.capropvar.pElems);
509 else if (pvar->vt & VT_ARRAY)
510 hr = SafeArrayDestroy(pvar->u.parray);
511 else
513 WARN("Invalid/unsupported type %d\n", pvar->vt);
514 hr = STG_E_INVALIDPARAMETER;
518 memset(pvar, 0, sizeof(*pvar));
519 return hr;
522 /***********************************************************************
523 * PropVariantCopy (combase.@)
525 HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest, const PROPVARIANT *pvarSrc)
527 ULONG len;
528 HRESULT hr;
530 TRACE("%p, %p vt %04x.\n", pvarDest, pvarSrc, pvarSrc->vt);
532 hr = propvar_validatetype(pvarSrc->vt);
533 if (FAILED(hr))
534 return DISP_E_BADVARTYPE;
536 /* this will deal with most cases */
537 *pvarDest = *pvarSrc;
539 switch (pvarSrc->vt)
541 case VT_EMPTY:
542 case VT_NULL:
543 case VT_I1:
544 case VT_UI1:
545 case VT_I2:
546 case VT_UI2:
547 case VT_BOOL:
548 case VT_DECIMAL:
549 case VT_I4:
550 case VT_UI4:
551 case VT_R4:
552 case VT_ERROR:
553 case VT_I8:
554 case VT_UI8:
555 case VT_INT:
556 case VT_UINT:
557 case VT_R8:
558 case VT_CY:
559 case VT_DATE:
560 case VT_FILETIME:
561 break;
562 case VT_DISPATCH:
563 case VT_UNKNOWN:
564 case VT_STREAM:
565 case VT_STREAMED_OBJECT:
566 case VT_STORAGE:
567 case VT_STORED_OBJECT:
568 if (pvarDest->u.pStream)
569 IStream_AddRef(pvarDest->u.pStream);
570 break;
571 case VT_CLSID:
572 pvarDest->u.puuid = CoTaskMemAlloc(sizeof(CLSID));
573 *pvarDest->u.puuid = *pvarSrc->u.puuid;
574 break;
575 case VT_LPSTR:
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));
582 break;
583 case VT_LPWSTR:
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));
590 break;
591 case VT_BLOB:
592 case VT_BLOB_OBJECT:
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);
599 break;
600 case VT_BSTR:
601 pvarDest->u.bstrVal = SysAllocString(pvarSrc->u.bstrVal);
602 break;
603 case VT_CF:
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);
613 break;
614 default:
615 if (pvarSrc->vt & VT_VECTOR)
617 int elemSize;
618 ULONG i;
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;
644 default:
645 FIXME("Invalid element type: %ul\n", pvarSrc->vt & ~VT_VECTOR);
646 return E_INVALIDARG;
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))
666 size_t strLen;
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))
677 size_t strLen;
678 for (i = 0; i < len; i++)
680 strLen = (lstrlenW(pvarSrc->u.calpwstr.pElems[i]) + 1) *
681 sizeof(WCHAR);
682 pvarDest->u.calpstr.pElems[i] = CoTaskMemAlloc(strLen);
683 memcpy(pvarDest->u.calpstr.pElems[i],
684 pvarSrc->u.calpstr.pElems[i], strLen);
687 else
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);
695 else
696 WARN("Invalid/unsupported type %d\n", pvarSrc->vt);
699 return S_OK;
702 /***********************************************************************
703 * CoFileTimeNow (combase.@)
705 HRESULT WINAPI CoFileTimeNow(FILETIME *filetime)
707 GetSystemTimeAsFileTime(filetime);
708 return S_OK;
711 /******************************************************************************
712 * CoCreateGuid (combase.@)
714 HRESULT WINAPI CoCreateGuid(GUID *guid)
716 RPC_STATUS status;
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;
733 HRESULT hr;
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);
739 if (SUCCEEDED(hr))
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);
747 return 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;
757 HRESULT hr;
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);
763 if (SUCCEEDED(hr))
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);
771 return hr;
774 /***********************************************************************
775 * CoCopyProxy (combase.@)
777 HRESULT WINAPI CoCopyProxy(IUnknown *proxy, IUnknown **proxy_copy)
779 IClientSecurity *client_security;
780 HRESULT hr;
782 TRACE("%p, %p.\n", proxy, proxy_copy);
784 hr = IUnknown_QueryInterface(proxy, &IID_IClientSecurity, (void **)&client_security);
785 if (SUCCEEDED(hr))
787 hr = IClientSecurity_CopyProxy(client_security, proxy, proxy_copy);
788 IClientSecurity_Release(client_security);
791 if (FAILED(hr)) ERR("-- failed with %#x.\n", hr);
792 return 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;
802 HRESULT hr;
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);
808 if (SUCCEEDED(hr))
810 hr = IServerSecurity_QueryBlanket(server_security, authn_service, authz_service, servername, authn_level,
811 imp_level, privs, capabilities);
812 IServerSecurity_Release(server_security);
815 return hr;
818 /***********************************************************************
819 * CoImpersonateClient (combase.@)
821 HRESULT WINAPI CoImpersonateClient(void)
823 IServerSecurity *server_security;
824 HRESULT hr;
826 TRACE("\n");
828 hr = CoGetCallContext(&IID_IServerSecurity, (void **)&server_security);
829 if (SUCCEEDED(hr))
831 hr = IServerSecurity_ImpersonateClient(server_security);
832 IServerSecurity_Release(server_security);
835 return hr;
838 /***********************************************************************
839 * CoRevertToSelf (combase.@)
841 HRESULT WINAPI CoRevertToSelf(void)
843 IServerSecurity *server_security;
844 HRESULT hr;
846 TRACE("\n");
848 hr = CoGetCallContext(&IID_IServerSecurity, (void **)&server_security);
849 if (SUCCEEDED(hr))
851 hr = IServerSecurity_RevertToSelf(server_security);
852 IServerSecurity_Release(server_security);
855 return hr;
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);
868 return S_OK;
871 /***********************************************************************
872 * CoGetObjectContext (combase.@)
874 HRESULT WINAPI CoGetObjectContext(REFIID riid, void **ppv)
876 IObjContext *context;
877 HRESULT hr;
879 TRACE("%s, %p.\n", debugstr_guid(riid), ppv);
881 *ppv = NULL;
882 hr = CoGetContextToken((ULONG_PTR *)&context);
883 if (FAILED(hr))
884 return hr;
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);
906 return E_NOTIMPL;
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);
916 return E_NOTIMPL;
919 /******************************************************************************
920 * CoGetTreatAsClass (combase.@)
922 HRESULT WINAPI CoGetTreatAsClass(REFCLSID clsidOld, CLSID *clsidNew)
924 WCHAR buffW[CHARS_IN_GUID];
925 LONG len = sizeof(buffW);
926 HRESULT hr = S_OK;
927 HKEY hkey = NULL;
929 TRACE("%s, %p.\n", debugstr_guid(clsidOld), clsidNew);
931 if (!clsidOld || !clsidNew)
932 return E_INVALIDARG;
934 *clsidNew = *clsidOld;
936 hr = open_key_for_clsid(clsidOld, L"TreatAs", KEY_READ, &hkey);
937 if (FAILED(hr))
939 hr = S_FALSE;
940 goto done;
943 if (RegQueryValueW(hkey, NULL, buffW, &len))
945 hr = S_FALSE;
946 goto done;
949 hr = CLSIDFromString(buffW, clsidNew);
950 if (FAILED(hr))
951 ERR("Failed to get CLSID from string %s, hr %#x.\n", debugstr_w(buffW), hr);
952 done:
953 if (hkey) RegCloseKey(hkey);
954 return hr;
957 /******************************************************************************
958 * ProgIDFromCLSID (combase.@)
960 HRESULT WINAPI DECLSPEC_HOTPATCH ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *progid)
962 ACTCTX_SECTION_KEYED_DATA data;
963 LONG progidlen = 0;
964 HKEY hkey;
965 HRESULT hr;
967 if (!progid)
968 return E_INVALIDARG;
970 *progid = NULL;
972 data.cbSize = sizeof(data);
973 if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,
974 clsid, &data))
976 struct comclassredirect_data *comclass = (struct comclassredirect_data *)data.lpData;
977 if (comclass->progid_len)
979 WCHAR *ptrW;
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));
986 return S_OK;
988 else
989 return REGDB_E_CLASSNOTREG;
992 hr = open_key_for_clsid(clsid, L"ProgID", KEY_READ, &hkey);
993 if (FAILED(hr))
994 return hr;
996 if (RegQueryValueW(hkey, NULL, NULL, &progidlen))
997 hr = REGDB_E_CLASSNOTREG;
999 if (hr == S_OK)
1001 *progid = CoTaskMemAlloc(progidlen * sizeof(WCHAR));
1002 if (*progid)
1004 if (RegQueryValueW(hkey, NULL, *progid, &progidlen))
1006 hr = REGDB_E_CLASSNOTREG;
1007 CoTaskMemFree(*progid);
1008 *progid = NULL;
1011 else
1012 hr = E_OUTOFMEMORY;
1015 RegCloseKey(hkey);
1016 return hr;
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'))))
1024 return FALSE;
1025 return TRUE;
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)
1041 int i;
1043 if (!s || s[0] != '{')
1045 memset(id, 0, sizeof(*id));
1046 if (!s) return TRUE;
1047 return FALSE;
1050 TRACE("%s -> %p\n", debugstr_w(s), id);
1052 /* In form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
1054 id->Data1 = 0;
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;
1062 id->Data2 = 0;
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;
1070 id->Data3 = 0;
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)
1080 if (i == 24)
1082 if (s[i] != '-') return FALSE;
1083 i++;
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')
1090 return TRUE;
1092 return FALSE;
1095 static HRESULT clsid_from_string_reg(LPCOLESTR progid, CLSID *clsid)
1097 WCHAR buf2[CHARS_IN_GUID];
1098 LONG buf2len = sizeof(buf2);
1099 HKEY xhkey;
1100 WCHAR *buf;
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))
1110 heap_free(buf);
1111 WARN("couldn't open key for ProgID %s\n", debugstr_w(progid));
1112 return CO_E_CLASSSTRING;
1114 heap_free(buf);
1116 if (RegQueryValueW(xhkey, NULL, buf2, &buf2len))
1118 RegCloseKey(xhkey);
1119 WARN("couldn't query clsid value for ProgID %s\n", debugstr_w(progid));
1120 return CO_E_CLASSSTRING;
1122 RegCloseKey(xhkey);
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,
1138 progid, &data))
1140 struct progidredirect_data *progiddata = (struct progidredirect_data *)data.lpData;
1141 CLSID *alias = (CLSID *)((BYTE *)data.lpSectionBase + progiddata->clsid_offset);
1142 *clsid = *alias;
1143 return S_OK;
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)
1164 CLSID tmp_id;
1165 HRESULT hr;
1167 if (!clsid)
1168 return E_INVALIDARG;
1170 if (guid_from_string(str, clsid))
1171 return S_OK;
1173 /* It appears a ProgID is also valid */
1174 hr = clsid_from_string_reg(str, &tmp_id);
1175 if (SUCCEEDED(hr))
1176 *clsid = tmp_id;
1178 return hr;
1181 /******************************************************************************
1182 * IIDFromString (combase.@)
1184 HRESULT WINAPI IIDFromString(LPCOLESTR str, IID *iid)
1186 TRACE("%s, %p\n", debugstr_w(str), iid);
1188 if (!str)
1190 memset(iid, 0, sizeof(*iid));
1191 return S_OK;
1194 /* length mismatch is a special case */
1195 if (lstrlenW(str) + 1 != CHARS_IN_GUID)
1196 return E_INVALIDARG;
1198 if (str[0] != '{')
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);
1211 return S_OK;
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)
1228 ULONG i;
1230 for (i = 0; i < count; i++)
1232 mqi[i].pItf = NULL;
1233 mqi[i].hr = hr;
1237 static HRESULT return_multi_qi(IUnknown *unk, DWORD count, MULTI_QI *mqi, BOOL include_unk)
1239 ULONG index = 0, fetched = 0;
1241 if (include_unk)
1243 mqi[0].hr = S_OK;
1244 mqi[0].pItf = unk;
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)
1252 fetched++;
1255 if (!include_unk)
1256 IUnknown_Release(unk);
1258 if (fetched == 0)
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,
1269 MULTI_QI *results)
1271 IPersistFile *pf = NULL;
1272 IUnknown *obj = NULL;
1273 CLSID clsid;
1274 HRESULT hr;
1276 if (!count || !results)
1277 return E_INVALIDARG;
1279 if (server_info)
1280 FIXME("() non-NULL server_info not supported\n");
1282 init_multi_qi(count, results, E_NOINTERFACE);
1284 if (!rclsid)
1286 hr = GetClassFile(filename, &clsid);
1287 if (FAILED(hr))
1289 ERR("Failed to get CLSID from a file.\n");
1290 return hr;
1293 rclsid = &clsid;
1296 hr = CoCreateInstance(rclsid, outer, cls_context, &IID_IUnknown, (void **)&obj);
1297 if (hr != S_OK)
1299 init_multi_qi(count, results, hr);
1300 return hr;
1303 /* Init from file */
1304 hr = IUnknown_QueryInterface(obj, &IID_IPersistFile, (void **)&pf);
1305 if (FAILED(hr))
1307 init_multi_qi(count, results, hr);
1308 IUnknown_Release(obj);
1309 return hr;
1312 hr = IPersistFile_Load(pf, filename, grfmode);
1313 IPersistFile_Release(pf);
1314 if (SUCCEEDED(hr))
1315 return return_multi_qi(obj, count, results, FALSE);
1316 else
1318 init_multi_qi(count, results, hr);
1319 IUnknown_Release(obj);
1320 return hr;
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;
1332 STATSTG stat;
1333 HRESULT hr;
1335 if (!count || !results || !storage)
1336 return E_INVALIDARG;
1338 if (server_info)
1339 FIXME("() non-NULL server_info not supported\n");
1341 init_multi_qi(count, results, E_NOINTERFACE);
1343 if (!rclsid)
1345 memset(&stat.clsid, 0, sizeof(stat.clsid));
1346 hr = IStorage_Stat(storage, &stat, STATFLAG_NONAME);
1347 if (FAILED(hr))
1349 ERR("Failed to get CLSID from a storage.\n");
1350 return hr;
1353 rclsid = &stat.clsid;
1356 hr = CoCreateInstance(rclsid, outer, cls_context, &IID_IUnknown, (void **)&obj);
1357 if (hr != S_OK)
1358 return hr;
1360 /* Init from IStorage */
1361 hr = IUnknown_QueryInterface(obj, &IID_IPersistStorage, (void **)&ps);
1362 if (FAILED(hr))
1363 ERR("failed to get IPersistStorage\n");
1365 if (ps)
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 };
1381 HRESULT hr;
1383 TRACE("%s, %p, %#x, %s, %p.\n", debugstr_guid(rclsid), outer, cls_context, debugstr_guid(riid), obj);
1385 if (!obj)
1386 return E_POINTER;
1388 hr = CoCreateInstanceEx(rclsid, outer, cls_context, NULL, 1, &multi_qi);
1389 *obj = multi_qi.pItf;
1390 return hr;
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;
1401 CLSID clsid;
1402 HRESULT hr;
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;
1409 if (server_info)
1410 FIXME("Server info is not supported.\n");
1412 init_multi_qi(count, results, E_NOINTERFACE);
1414 hr = CoGetTreatAsClass(rclsid, &clsid);
1415 if (FAILED(hr))
1416 clsid = *rclsid;
1418 hr = CoGetClassObject(&clsid, cls_context, NULL, &IID_IClassFactory, (void **)&factory);
1419 if (FAILED(hr))
1420 return hr;
1422 hr = IClassFactory_CreateInstance(factory, outer, results[0].pIID, (void **)&unk);
1423 IClassFactory_Release(factory);
1424 if (FAILED(hr))
1426 if (hr == CLASS_E_NOAGGREGATION && outer)
1427 FIXME("Class %s does not support aggregation\n", debugstr_guid(&clsid));
1428 else
1429 FIXME("no instance created for interface %s of class %s, hr %#x.\n",
1430 debugstr_guid(results[0].pIID), debugstr_guid(&clsid), hr);
1431 return 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;
1451 HRESULT hr;
1453 TRACE("%s, %p\n", debugstr_guid(riid), obj);
1455 if (FAILED(hr = com_get_tlsdata(&tlsdata)))
1456 return hr;
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;
1470 HRESULT hr;
1472 TRACE("%p, %p\n", context, old_context);
1474 if (FAILED(hr = com_get_tlsdata(&tlsdata)))
1475 return hr;
1477 /* Reference counts are not touched. */
1478 *old_context = tlsdata->call_state;
1479 tlsdata->call_state = context;
1481 return S_OK;
1484 /******************************************************************************
1485 * CoRegisterInitializeSpy (combase.@)
1487 HRESULT WINAPI CoRegisterInitializeSpy(IInitializeSpy *spy, ULARGE_INTEGER *cookie)
1489 struct tlsdata *tlsdata;
1490 struct init_spy *entry;
1491 unsigned int id;
1492 HRESULT hr;
1494 TRACE("%p, %p\n", spy, cookie);
1496 if (!spy || !cookie)
1497 return E_INVALIDARG;
1499 if (FAILED(hr = com_get_tlsdata(&tlsdata)))
1500 return hr;
1502 hr = IInitializeSpy_QueryInterface(spy, &IID_IInitializeSpy, (void **)&spy);
1503 if (FAILED(hr))
1504 return hr;
1506 entry = heap_alloc(sizeof(*entry));
1507 if (!entry)
1509 IInitializeSpy_Release(spy);
1510 return E_OUTOFMEMORY;
1513 entry->spy = spy;
1515 id = 0;
1516 while (get_spy_entry(tlsdata, id) != NULL)
1518 id++;
1521 entry->id = id;
1522 list_add_head(&tlsdata->spies, &entry->entry);
1524 cookie->u.HighPart = GetCurrentThreadId();
1525 cookie->u.LowPart = entry->id;
1527 return S_OK;
1530 /******************************************************************************
1531 * CoRevokeInitializeSpy (combase.@)
1533 HRESULT WINAPI CoRevokeInitializeSpy(ULARGE_INTEGER cookie)
1535 struct tlsdata *tlsdata;
1536 struct init_spy *spy;
1537 HRESULT hr;
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)))
1545 return hr;
1547 if (!(spy = get_spy_entry(tlsdata, cookie.u.LowPart))) return E_INVALIDARG;
1549 IInitializeSpy_Release(spy->spy);
1550 spy->spy = NULL;
1551 if (!tlsdata->spies_lock)
1553 list_remove(&spy->entry);
1554 heap_free(spy);
1556 return S_OK;
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,
1572 DWORD *index)
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;
1578 UINT exit_code;
1579 HRESULT hr;
1581 TRACE("%#x, %#x, %u, %p, %p\n", flags, timeout, handle_count, handles, index);
1583 if (!index)
1584 return E_INVALIDARG;
1586 *index = 0;
1588 if (!handles)
1589 return E_INVALIDARG;
1591 if (!handle_count)
1592 return RPC_E_NO_SYNC;
1594 if (FAILED(hr = com_get_tlsdata(&tlsdata)))
1595 return hr;
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();
1607 while (TRUE)
1609 DWORD now = GetTickCount(), res;
1611 if (now - start_time > timeout)
1613 hr = RPC_S_CALLPENDING;
1614 break;
1617 if (message_loop)
1619 TRACE("waiting for rpc completion or window message\n");
1621 res = WAIT_TIMEOUT;
1623 if (check_apc)
1625 res = WaitForMultipleObjectsEx(handle_count, handles, !!(flags & COWAIT_WAITALL), 0, TRUE);
1626 check_apc = FALSE;
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 */
1636 int msg_count = 0;
1637 MSG msg;
1639 /* call message filter */
1641 if (apt->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);
1648 switch (be_handled)
1650 case PENDINGMSG_CANCELCALL:
1651 WARN("call canceled\n");
1652 hr = RPC_E_CALL_CANCELED;
1653 break;
1654 case PENDINGMSG_WAITNOPROCESS:
1655 case PENDINGMSG_WAITDEFPROCESS:
1656 default:
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. */
1661 break;
1665 if (!apt->win)
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");
1679 post_quit = TRUE;
1680 exit_code = msg.wParam;
1682 else
1684 TRACE("Received message whilst waiting for RPC: 0x%04x\n", msg.message);
1685 TranslateMessage(&msg);
1686 DispatchMessageW(&msg);
1689 continue;
1692 else
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));
1700 switch (res)
1702 case WAIT_TIMEOUT:
1703 hr = RPC_S_CALLPENDING;
1704 break;
1705 case WAIT_FAILED:
1706 hr = HRESULT_FROM_WIN32(GetLastError());
1707 break;
1708 default:
1709 *index = res;
1710 break;
1712 break;
1714 if (post_quit) PostQuitMessage(exit_code);
1716 TRACE("-- 0x%08x\n", hr);
1718 return 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;
1740 if (filter)
1741 IMessageFilter_AddRef(filter);
1743 EnterCriticalSection(&apt->cs);
1745 old_filter = apt->filter;
1746 apt->filter = filter;
1748 LeaveCriticalSection(&apt->cs);
1750 if (ret_filter)
1751 *ret_filter = old_filter;
1752 else if (old_filter)
1753 IMessageFilter_Release(old_filter);
1755 return S_OK;
1758 void WINAPI InternalRevokeAllPSClsids(void)
1760 struct registered_ps *cur, *cur2;
1762 EnterCriticalSection(&cs_registered_ps);
1764 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &registered_proxystubs, struct registered_ps, entry)
1766 list_remove(&cur->entry);
1767 heap_free(cur);
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];
1776 HKEY hkey;
1777 DWORD len;
1779 access |= KEY_READ;
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;
1787 RegCloseKey(hkey);
1789 if (CLSIDFromString(value, pclsid) != NOERROR)
1790 return REGDB_E_IIDNOTREG;
1792 return S_OK;
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;
1806 BOOL is_wow64;
1807 HRESULT hr;
1809 TRACE("%s, %p\n", debugstr_guid(riid), pclsid);
1811 if (!InternalIsInitialized())
1813 ERR("apartment not initialised\n");
1814 return CO_E_NOTINITIALIZED;
1817 if (!pclsid)
1818 return E_INVALIDARG;
1820 EnterCriticalSection(&cs_registered_ps);
1822 LIST_FOR_EACH_ENTRY(cur, &registered_proxystubs, struct registered_ps, entry)
1824 if (IsEqualIID(&cur->iid, riid))
1826 *pclsid = cur->clsid;
1827 LeaveCriticalSection(&cs_registered_ps);
1828 return S_OK;
1832 LeaveCriticalSection(&cs_registered_ps);
1834 data.cbSize = sizeof(data);
1835 if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION,
1836 riid, &data))
1838 struct ifacepsredirect_data *ifaceps = (struct ifacepsredirect_data *)data.lpData;
1839 *pclsid = ifaceps->iid;
1840 return S_OK;
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);
1852 if (hr == S_OK)
1853 TRACE("() Returning CLSID %s\n", debugstr_guid(pclsid));
1854 else
1855 WARN("No PSFactoryBuffer object is registered for IID %s\n", debugstr_guid(riid));
1857 return hr;
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, &registered_proxystubs, struct registered_ps, entry)
1879 if (IsEqualIID(&cur->iid, riid))
1881 cur->clsid = *rclsid;
1882 LeaveCriticalSection(&cs_registered_ps);
1883 return S_OK;
1887 cur = heap_alloc(sizeof(*cur));
1888 if (!cur)
1890 LeaveCriticalSection(&cs_registered_ps);
1891 return E_OUTOFMEMORY;
1894 cur->iid = *riid;
1895 cur->clsid = *rclsid;
1896 list_add_head(&registered_proxystubs, &cur->entry);
1898 LeaveCriticalSection(&cs_registered_ps);
1900 return S_OK;
1903 struct thread_context
1905 IComThreadingInfo IComThreadingInfo_iface;
1906 IContextCallback IContextCallback_iface;
1907 IObjContext IObjContext_iface;
1908 LONG refcount;
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);
1930 *obj = NULL;
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;
1946 if (*obj)
1948 IUnknown_AddRef((IUnknown *)*obj);
1949 return S_OK;
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)
1970 heap_free(context);
1971 return 0;
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;
1989 APTTYPE apttype;
1990 HRESULT hr;
1992 hr = CoGetApartmentType(&apttype, &qualifier);
1993 if (FAILED(hr))
1994 return hr;
1996 TRACE("%p\n", thdtype);
1998 switch (apttype)
2000 case APTTYPE_STA:
2001 case APTTYPE_MAINSTA:
2002 *thdtype = THDTYPE_PROCESSMESSAGES;
2003 break;
2004 default:
2005 *thdtype = THDTYPE_BLOCKMESSAGES;
2006 break;
2008 return S_OK;
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));
2022 return E_NOTIMPL;
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);
2059 return E_NOTIMPL;
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);
2092 return E_NOTIMPL;
2095 static HRESULT WINAPI thread_object_context_RemoveProperty(IObjContext *iface, REFGUID propid)
2097 FIXME("%p, %s\n", iface, debugstr_guid(propid));
2099 return E_NOTIMPL;
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);
2106 return E_NOTIMPL;
2109 static HRESULT WINAPI thread_object_context_EnumContextProps(IObjContext *iface, IEnumContextProps **props)
2111 FIXME("%p, %p\n", iface, props);
2113 return E_NOTIMPL;
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;
2175 HRESULT hr;
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)))
2186 return hr;
2188 if (!token)
2189 return E_POINTER;
2191 if (!tlsdata->context_token)
2193 struct thread_context *context;
2195 context = heap_alloc_zero(sizeof(*context));
2196 if (!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);
2212 return S_OK;
2215 /***********************************************************************
2216 * CoGetCurrentLogicalThreadId (combase.@)
2218 HRESULT WINAPI CoGetCurrentLogicalThreadId(GUID *id)
2220 struct tlsdata *tlsdata;
2221 HRESULT hr;
2223 if (!id)
2224 return E_INVALIDARG;
2226 if (FAILED(hr = com_get_tlsdata(&tlsdata)))
2227 return hr;
2229 if (IsEqualGUID(&tlsdata->causality_id, &GUID_NULL))
2230 CoCreateGuid(&tlsdata->causality_id);
2232 *id = tlsdata->causality_id;
2234 return S_OK;
2237 /******************************************************************************
2238 * CoGetCurrentProcess (combase.@)
2240 DWORD WINAPI CoGetCurrentProcess(void)
2242 struct tlsdata *tlsdata;
2244 if (FAILED(com_get_tlsdata(&tlsdata)))
2245 return 0;
2247 if (!tlsdata->thread_seqid)
2248 tlsdata->thread_seqid = rpcss_get_next_seqid();
2250 return tlsdata->thread_seqid;