Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/combase/combase.c
8525 views
1
/*
2
* Copyright 2005 Juan Lang
3
* Copyright 2005-2006 Robert Shearman (for CodeWeavers)
4
*
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.
9
*
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.
14
*
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
18
*/
19
20
#define COBJMACROS
21
#include "ntstatus.h"
22
#define WIN32_NO_STATUS
23
#define USE_COM_CONTEXT_DEF
24
#include "objbase.h"
25
#include "ctxtcall.h"
26
#include "oleauto.h"
27
#include "dde.h"
28
#include "winternl.h"
29
30
#include "combase_private.h"
31
32
#include "wine/debug.h"
33
34
WINE_DEFAULT_DEBUG_CHANNEL(ole);
35
36
HINSTANCE hProxyDll;
37
38
static ULONG_PTR global_options[COMGLB_PROPERTIES_RESERVED3 + 1];
39
40
/* Ole32 exports */
41
extern void WINAPI DestroyRunningObjectTable(void);
42
extern HRESULT WINAPI Ole32DllGetClassObject(REFCLSID rclsid, REFIID riid, void **obj);
43
44
/*
45
* Number of times CoInitialize is called. It is decreased every time CoUninitialize is called. When it hits 0, the COM libraries are freed
46
*/
47
static LONG com_lockcount;
48
49
static LONG com_server_process_refcount;
50
51
struct comclassredirect_data
52
{
53
ULONG size;
54
ULONG flags;
55
DWORD model;
56
GUID clsid;
57
GUID alias;
58
GUID clsid2;
59
GUID tlbid;
60
ULONG name_len;
61
ULONG name_offset;
62
ULONG progid_len;
63
ULONG progid_offset;
64
ULONG clrdata_len;
65
ULONG clrdata_offset;
66
DWORD miscstatus;
67
DWORD miscstatuscontent;
68
DWORD miscstatusthumbnail;
69
DWORD miscstatusicon;
70
DWORD miscstatusdocprint;
71
};
72
73
struct ifacepsredirect_data
74
{
75
ULONG size;
76
DWORD mask;
77
GUID iid;
78
ULONG nummethods;
79
GUID tlbid;
80
GUID base;
81
ULONG name_len;
82
ULONG name_offset;
83
};
84
85
struct progidredirect_data
86
{
87
ULONG size;
88
DWORD reserved;
89
ULONG clsid_offset;
90
};
91
92
struct init_spy
93
{
94
struct list entry;
95
IInitializeSpy *spy;
96
unsigned int id;
97
};
98
99
struct registered_ps
100
{
101
struct list entry;
102
IID iid;
103
CLSID clsid;
104
};
105
106
static struct list registered_proxystubs = LIST_INIT(registered_proxystubs);
107
108
static CRITICAL_SECTION cs_registered_ps;
109
static CRITICAL_SECTION_DEBUG psclsid_cs_debug =
110
{
111
0, 0, &cs_registered_ps,
112
{ &psclsid_cs_debug.ProcessLocksList, &psclsid_cs_debug.ProcessLocksList },
113
0, 0, { (DWORD_PTR)(__FILE__ ": cs_registered_psclsid_list") }
114
};
115
static CRITICAL_SECTION cs_registered_ps = { &psclsid_cs_debug, -1, 0, 0, 0, 0 };
116
117
struct registered_class
118
{
119
struct list entry;
120
CLSID clsid;
121
OXID apartment_id;
122
IUnknown *object;
123
DWORD clscontext;
124
DWORD flags;
125
unsigned int cookie;
126
unsigned int rpcss_cookie;
127
};
128
129
static struct list registered_classes = LIST_INIT(registered_classes);
130
131
static CRITICAL_SECTION registered_classes_cs;
132
static CRITICAL_SECTION_DEBUG registered_classes_cs_debug =
133
{
134
0, 0, &registered_classes_cs,
135
{ &registered_classes_cs_debug.ProcessLocksList, &registered_classes_cs_debug.ProcessLocksList },
136
0, 0, { (DWORD_PTR)(__FILE__ ": registered_classes_cs") }
137
};
138
static CRITICAL_SECTION registered_classes_cs = { &registered_classes_cs_debug, -1, 0, 0, 0, 0 };
139
140
IUnknown * com_get_registered_class_object(const struct apartment *apt, REFCLSID rclsid, DWORD clscontext)
141
{
142
struct registered_class *cur;
143
IUnknown *object = NULL;
144
145
EnterCriticalSection(&registered_classes_cs);
146
147
LIST_FOR_EACH_ENTRY(cur, &registered_classes, struct registered_class, entry)
148
{
149
if ((apt->oxid == cur->apartment_id) &&
150
(clscontext & cur->clscontext) &&
151
IsEqualGUID(&cur->clsid, rclsid))
152
{
153
object = cur->object;
154
IUnknown_AddRef(cur->object);
155
break;
156
}
157
}
158
159
LeaveCriticalSection(&registered_classes_cs);
160
161
return object;
162
}
163
164
static struct init_spy *get_spy_entry(struct tlsdata *tlsdata, unsigned int id)
165
{
166
struct init_spy *spy;
167
168
LIST_FOR_EACH_ENTRY(spy, &tlsdata->spies, struct init_spy, entry)
169
{
170
if (id == spy->id && spy->spy)
171
return spy;
172
}
173
174
return NULL;
175
}
176
177
static NTSTATUS create_key(HKEY *retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr)
178
{
179
NTSTATUS status = NtCreateKey((HANDLE *)retkey, access, attr, 0, NULL, 0, NULL);
180
181
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
182
{
183
HANDLE subkey;
184
WCHAR *buffer = attr->ObjectName->Buffer;
185
DWORD pos = 0, i = 0, len = attr->ObjectName->Length / sizeof(WCHAR);
186
UNICODE_STRING str;
187
OBJECT_ATTRIBUTES attr2 = *attr;
188
189
while (i < len && buffer[i] != '\\') i++;
190
if (i == len) return status;
191
192
attr2.ObjectName = &str;
193
194
while (i < len)
195
{
196
str.Buffer = buffer + pos;
197
str.Length = (i - pos) * sizeof(WCHAR);
198
status = NtCreateKey(&subkey, access, &attr2, 0, NULL, 0, NULL);
199
if (attr2.RootDirectory != attr->RootDirectory) NtClose(attr2.RootDirectory);
200
if (status) return status;
201
attr2.RootDirectory = subkey;
202
while (i < len && buffer[i] == '\\') i++;
203
pos = i;
204
while (i < len && buffer[i] != '\\') i++;
205
}
206
str.Buffer = buffer + pos;
207
str.Length = (i - pos) * sizeof(WCHAR);
208
status = NtCreateKey((HANDLE *)retkey, access, &attr2, 0, NULL, 0, NULL);
209
if (attr2.RootDirectory != attr->RootDirectory) NtClose(attr2.RootDirectory);
210
}
211
return status;
212
}
213
214
static HKEY classes_root_hkey;
215
216
static HKEY create_classes_root_hkey(DWORD access)
217
{
218
HKEY hkey, ret = 0;
219
OBJECT_ATTRIBUTES attr;
220
UNICODE_STRING name = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Classes");
221
222
attr.Length = sizeof(attr);
223
attr.RootDirectory = 0;
224
attr.ObjectName = &name;
225
attr.Attributes = 0;
226
attr.SecurityDescriptor = NULL;
227
attr.SecurityQualityOfService = NULL;
228
229
if (create_key( &hkey, access, &attr )) return 0;
230
TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey );
231
232
if (!(access & KEY_WOW64_64KEY))
233
{
234
if (!(ret = InterlockedCompareExchangePointer( (void **)&classes_root_hkey, hkey, 0 )))
235
ret = hkey;
236
else
237
NtClose( hkey ); /* somebody beat us to it */
238
}
239
else
240
ret = hkey;
241
return ret;
242
}
243
244
static HKEY get_classes_root_hkey(HKEY hkey, REGSAM access);
245
246
static LSTATUS create_classes_key(HKEY hkey, const WCHAR *name, REGSAM access, HKEY *retkey)
247
{
248
OBJECT_ATTRIBUTES attr;
249
UNICODE_STRING nameW;
250
251
if (!(hkey = get_classes_root_hkey(hkey, access)))
252
return ERROR_INVALID_HANDLE;
253
254
attr.Length = sizeof(attr);
255
attr.RootDirectory = hkey;
256
attr.ObjectName = &nameW;
257
attr.Attributes = 0;
258
attr.SecurityDescriptor = NULL;
259
attr.SecurityQualityOfService = NULL;
260
RtlInitUnicodeString( &nameW, name );
261
262
return RtlNtStatusToDosError(create_key(retkey, access, &attr));
263
}
264
265
static HKEY get_classes_root_hkey(HKEY hkey, REGSAM access)
266
{
267
HKEY ret = hkey;
268
const BOOL is_win64 = sizeof(void*) > sizeof(int);
269
const BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY);
270
271
if (hkey == HKEY_CLASSES_ROOT &&
272
((access & KEY_WOW64_64KEY) || !(ret = classes_root_hkey)))
273
ret = create_classes_root_hkey(MAXIMUM_ALLOWED | (access & KEY_WOW64_64KEY));
274
if (force_wow32 && ret && ret == classes_root_hkey)
275
{
276
access &= ~KEY_WOW64_32KEY;
277
if (create_classes_key(classes_root_hkey, L"Wow6432Node", access, &hkey))
278
return 0;
279
ret = hkey;
280
}
281
282
return ret;
283
}
284
285
static LSTATUS open_classes_key(HKEY hkey, const WCHAR *name, REGSAM access, HKEY *retkey)
286
{
287
OBJECT_ATTRIBUTES attr;
288
UNICODE_STRING nameW;
289
290
if (!(hkey = get_classes_root_hkey(hkey, access)))
291
return ERROR_INVALID_HANDLE;
292
293
attr.Length = sizeof(attr);
294
attr.RootDirectory = hkey;
295
attr.ObjectName = &nameW;
296
attr.Attributes = 0;
297
attr.SecurityDescriptor = NULL;
298
attr.SecurityQualityOfService = NULL;
299
RtlInitUnicodeString( &nameW, name );
300
301
return RtlNtStatusToDosError(NtOpenKey((HANDLE *)retkey, access, &attr));
302
}
303
304
HRESULT open_key_for_clsid(REFCLSID clsid, const WCHAR *keyname, REGSAM access, HKEY *subkey)
305
{
306
static const WCHAR clsidW[] = L"CLSID\\";
307
WCHAR path[CHARS_IN_GUID + ARRAY_SIZE(clsidW) - 1];
308
LONG res;
309
HKEY key;
310
311
lstrcpyW(path, clsidW);
312
StringFromGUID2(clsid, path + lstrlenW(clsidW), CHARS_IN_GUID);
313
res = open_classes_key(HKEY_CLASSES_ROOT, path, access, &key);
314
if (res == ERROR_FILE_NOT_FOUND)
315
return REGDB_E_CLASSNOTREG;
316
else if (res != ERROR_SUCCESS)
317
return REGDB_E_READREGDB;
318
319
if (!keyname)
320
{
321
*subkey = key;
322
return S_OK;
323
}
324
325
res = open_classes_key(key, keyname, access, subkey);
326
RegCloseKey(key);
327
if (res == ERROR_FILE_NOT_FOUND)
328
return REGDB_E_KEYMISSING;
329
else if (res != ERROR_SUCCESS)
330
return REGDB_E_READREGDB;
331
332
return S_OK;
333
}
334
335
/* open HKCR\\AppId\\{string form of appid clsid} key */
336
HRESULT open_appidkey_from_clsid(REFCLSID clsid, REGSAM access, HKEY *subkey)
337
{
338
static const WCHAR appidkeyW[] = L"AppId\\";
339
DWORD res;
340
WCHAR buf[CHARS_IN_GUID];
341
WCHAR keyname[ARRAY_SIZE(appidkeyW) + CHARS_IN_GUID];
342
DWORD size;
343
HKEY hkey;
344
DWORD type;
345
HRESULT hr;
346
347
/* read the AppID value under the class's key */
348
hr = open_key_for_clsid(clsid, NULL, access, &hkey);
349
if (FAILED(hr))
350
return hr;
351
352
size = sizeof(buf);
353
res = RegQueryValueExW(hkey, L"AppId", NULL, &type, (LPBYTE)buf, &size);
354
RegCloseKey(hkey);
355
if (res == ERROR_FILE_NOT_FOUND)
356
return REGDB_E_KEYMISSING;
357
else if (res != ERROR_SUCCESS || type!=REG_SZ)
358
return REGDB_E_READREGDB;
359
360
lstrcpyW(keyname, appidkeyW);
361
lstrcatW(keyname, buf);
362
res = open_classes_key(HKEY_CLASSES_ROOT, keyname, access, subkey);
363
if (res == ERROR_FILE_NOT_FOUND)
364
return REGDB_E_KEYMISSING;
365
else if (res != ERROR_SUCCESS)
366
return REGDB_E_READREGDB;
367
368
return S_OK;
369
}
370
371
/***********************************************************************
372
* InternalIsProcessInitialized (combase.@)
373
*/
374
BOOL WINAPI InternalIsProcessInitialized(void)
375
{
376
struct apartment *apt;
377
378
if (!(apt = apartment_get_current_or_mta()))
379
return FALSE;
380
apartment_release(apt);
381
382
return TRUE;
383
}
384
385
/***********************************************************************
386
* InternalTlsAllocData (combase.@)
387
*/
388
HRESULT WINAPI InternalTlsAllocData(struct tlsdata **data)
389
{
390
if (!(*data = calloc(1, sizeof(**data))))
391
return E_OUTOFMEMORY;
392
393
list_init(&(*data)->spies);
394
NtCurrentTeb()->ReservedForOle = *data;
395
396
return S_OK;
397
}
398
399
static void com_cleanup_tlsdata(void)
400
{
401
struct tlsdata *tlsdata = NtCurrentTeb()->ReservedForOle;
402
struct init_spy *cursor, *cursor2;
403
404
if (!tlsdata)
405
return;
406
407
if (tlsdata->apt)
408
apartment_release(tlsdata->apt);
409
if (tlsdata->implicit_mta_cookie)
410
apartment_decrement_mta_usage(tlsdata->implicit_mta_cookie);
411
412
if (tlsdata->errorinfo)
413
IErrorInfo_Release(tlsdata->errorinfo);
414
if (tlsdata->state)
415
IUnknown_Release(tlsdata->state);
416
417
LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &tlsdata->spies, struct init_spy, entry)
418
{
419
list_remove(&cursor->entry);
420
if (cursor->spy)
421
IInitializeSpy_Release(cursor->spy);
422
free(cursor);
423
}
424
425
if (tlsdata->context_token)
426
IObjContext_Release(tlsdata->context_token);
427
428
free(tlsdata);
429
NtCurrentTeb()->ReservedForOle = NULL;
430
}
431
432
struct global_options
433
{
434
IGlobalOptions IGlobalOptions_iface;
435
LONG refcount;
436
};
437
438
static inline struct global_options *impl_from_IGlobalOptions(IGlobalOptions *iface)
439
{
440
return CONTAINING_RECORD(iface, struct global_options, IGlobalOptions_iface);
441
}
442
443
static HRESULT WINAPI global_options_QueryInterface(IGlobalOptions *iface, REFIID riid, void **ppv)
444
{
445
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), ppv);
446
447
if (IsEqualGUID(&IID_IGlobalOptions, riid) || IsEqualGUID(&IID_IUnknown, riid))
448
{
449
*ppv = iface;
450
}
451
else
452
{
453
*ppv = NULL;
454
return E_NOINTERFACE;
455
}
456
457
IUnknown_AddRef((IUnknown *)*ppv);
458
return S_OK;
459
}
460
461
static ULONG WINAPI global_options_AddRef(IGlobalOptions *iface)
462
{
463
struct global_options *options = impl_from_IGlobalOptions(iface);
464
LONG refcount = InterlockedIncrement(&options->refcount);
465
466
TRACE("%p, refcount %ld.\n", iface, refcount);
467
468
return refcount;
469
}
470
471
static ULONG WINAPI global_options_Release(IGlobalOptions *iface)
472
{
473
struct global_options *options = impl_from_IGlobalOptions(iface);
474
LONG refcount = InterlockedDecrement(&options->refcount);
475
476
TRACE("%p, refcount %ld.\n", iface, refcount);
477
478
if (!refcount)
479
free(options);
480
481
return refcount;
482
}
483
484
static HRESULT WINAPI global_options_Set(IGlobalOptions *iface, GLOBALOPT_PROPERTIES property, ULONG_PTR value)
485
{
486
FIXME("%p, %u, %Ix.\n", iface, property, value);
487
488
return S_OK;
489
}
490
491
static HRESULT WINAPI global_options_Query(IGlobalOptions *iface, GLOBALOPT_PROPERTIES property, ULONG_PTR *value)
492
{
493
TRACE("%p, %u, %p.\n", iface, property, value);
494
495
if (property < COMGLB_EXCEPTION_HANDLING || property > COMGLB_PROPERTIES_RESERVED3)
496
return E_INVALIDARG;
497
498
*value = global_options[property];
499
500
return S_OK;
501
}
502
503
static const IGlobalOptionsVtbl global_options_vtbl =
504
{
505
global_options_QueryInterface,
506
global_options_AddRef,
507
global_options_Release,
508
global_options_Set,
509
global_options_Query
510
};
511
512
static HRESULT WINAPI class_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
513
{
514
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), ppv);
515
516
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
517
{
518
*ppv = iface;
519
return S_OK;
520
}
521
522
*ppv = NULL;
523
return E_NOINTERFACE;
524
}
525
526
static ULONG WINAPI class_factory_AddRef(IClassFactory *iface)
527
{
528
return 2;
529
}
530
531
static ULONG WINAPI class_factory_Release(IClassFactory *iface)
532
{
533
return 1;
534
}
535
536
static HRESULT WINAPI class_factory_LockServer(IClassFactory *iface, BOOL fLock)
537
{
538
TRACE("%d\n", fLock);
539
540
return S_OK;
541
}
542
543
static HRESULT WINAPI global_options_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
544
{
545
struct global_options *object;
546
HRESULT hr;
547
548
TRACE("%p, %s, %p.\n", outer, debugstr_guid(riid), ppv);
549
550
if (outer)
551
return E_INVALIDARG;
552
553
if (!(object = malloc(sizeof(*object))))
554
return E_OUTOFMEMORY;
555
object->IGlobalOptions_iface.lpVtbl = &global_options_vtbl;
556
object->refcount = 1;
557
558
hr = IGlobalOptions_QueryInterface(&object->IGlobalOptions_iface, riid, ppv);
559
IGlobalOptions_Release(&object->IGlobalOptions_iface);
560
return hr;
561
}
562
563
static const IClassFactoryVtbl global_options_factory_vtbl =
564
{
565
class_factory_QueryInterface,
566
class_factory_AddRef,
567
class_factory_Release,
568
global_options_CreateInstance,
569
class_factory_LockServer
570
};
571
572
static IClassFactory global_options_factory = { &global_options_factory_vtbl };
573
574
static HRESULT get_builtin_class_factory(REFCLSID rclsid, REFIID riid, void **obj)
575
{
576
if (IsEqualCLSID(rclsid, &CLSID_GlobalOptions))
577
return IClassFactory_QueryInterface(&global_options_factory, riid, obj);
578
return E_UNEXPECTED;
579
}
580
581
/***********************************************************************
582
* FreePropVariantArray (combase.@)
583
*/
584
HRESULT WINAPI FreePropVariantArray(ULONG count, PROPVARIANT *rgvars)
585
{
586
ULONG i;
587
588
TRACE("%lu, %p.\n", count, rgvars);
589
590
if (!rgvars)
591
return E_INVALIDARG;
592
593
for (i = 0; i < count; ++i)
594
PropVariantClear(&rgvars[i]);
595
596
return S_OK;
597
}
598
599
static HRESULT propvar_validatetype(VARTYPE vt)
600
{
601
switch (vt)
602
{
603
case VT_EMPTY:
604
case VT_NULL:
605
case VT_I1:
606
case VT_I2:
607
case VT_I4:
608
case VT_I8:
609
case VT_R4:
610
case VT_R8:
611
case VT_CY:
612
case VT_DATE:
613
case VT_BSTR:
614
case VT_ERROR:
615
case VT_BOOL:
616
case VT_DECIMAL:
617
case VT_UI1:
618
case VT_UI2:
619
case VT_UI4:
620
case VT_UI8:
621
case VT_INT:
622
case VT_UINT:
623
case VT_LPSTR:
624
case VT_LPWSTR:
625
case VT_FILETIME:
626
case VT_BLOB:
627
case VT_DISPATCH:
628
case VT_UNKNOWN:
629
case VT_STREAM:
630
case VT_STORAGE:
631
case VT_STREAMED_OBJECT:
632
case VT_STORED_OBJECT:
633
case VT_BLOB_OBJECT:
634
case VT_CF:
635
case VT_CLSID:
636
case VT_I1|VT_VECTOR:
637
case VT_I2|VT_VECTOR:
638
case VT_I4|VT_VECTOR:
639
case VT_I8|VT_VECTOR:
640
case VT_R4|VT_VECTOR:
641
case VT_R8|VT_VECTOR:
642
case VT_CY|VT_VECTOR:
643
case VT_DATE|VT_VECTOR:
644
case VT_BSTR|VT_VECTOR:
645
case VT_ERROR|VT_VECTOR:
646
case VT_BOOL|VT_VECTOR:
647
case VT_VARIANT|VT_VECTOR:
648
case VT_UI1|VT_VECTOR:
649
case VT_UI2|VT_VECTOR:
650
case VT_UI4|VT_VECTOR:
651
case VT_UI8|VT_VECTOR:
652
case VT_LPSTR|VT_VECTOR:
653
case VT_LPWSTR|VT_VECTOR:
654
case VT_FILETIME|VT_VECTOR:
655
case VT_CF|VT_VECTOR:
656
case VT_CLSID|VT_VECTOR:
657
case VT_ARRAY|VT_I1:
658
case VT_ARRAY|VT_UI1:
659
case VT_ARRAY|VT_I2:
660
case VT_ARRAY|VT_UI2:
661
case VT_ARRAY|VT_I4:
662
case VT_ARRAY|VT_UI4:
663
case VT_ARRAY|VT_INT:
664
case VT_ARRAY|VT_UINT:
665
case VT_ARRAY|VT_R4:
666
case VT_ARRAY|VT_R8:
667
case VT_ARRAY|VT_CY:
668
case VT_ARRAY|VT_DATE:
669
case VT_ARRAY|VT_BSTR:
670
case VT_ARRAY|VT_BOOL:
671
case VT_ARRAY|VT_DECIMAL:
672
case VT_ARRAY|VT_DISPATCH:
673
case VT_ARRAY|VT_UNKNOWN:
674
case VT_ARRAY|VT_ERROR:
675
case VT_ARRAY|VT_VARIANT:
676
return S_OK;
677
}
678
WARN("Bad type %d\n", vt);
679
return STG_E_INVALIDPARAMETER;
680
}
681
682
static void propvar_free_cf_array(ULONG count, CLIPDATA *data)
683
{
684
ULONG i;
685
for (i = 0; i < count; ++i)
686
CoTaskMemFree(data[i].pClipData);
687
}
688
689
/***********************************************************************
690
* PropVariantClear (combase.@)
691
*/
692
HRESULT WINAPI PropVariantClear(PROPVARIANT *pvar)
693
{
694
HRESULT hr;
695
696
TRACE("%p.\n", pvar);
697
698
if (!pvar)
699
return S_OK;
700
701
hr = propvar_validatetype(pvar->vt);
702
if (FAILED(hr))
703
{
704
memset(pvar, 0, sizeof(*pvar));
705
return hr;
706
}
707
708
switch (pvar->vt)
709
{
710
case VT_EMPTY:
711
case VT_NULL:
712
case VT_I1:
713
case VT_I2:
714
case VT_I4:
715
case VT_I8:
716
case VT_R4:
717
case VT_R8:
718
case VT_CY:
719
case VT_DATE:
720
case VT_ERROR:
721
case VT_BOOL:
722
case VT_DECIMAL:
723
case VT_UI1:
724
case VT_UI2:
725
case VT_UI4:
726
case VT_UI8:
727
case VT_INT:
728
case VT_UINT:
729
case VT_FILETIME:
730
break;
731
case VT_DISPATCH:
732
case VT_UNKNOWN:
733
case VT_STREAM:
734
case VT_STREAMED_OBJECT:
735
case VT_STORAGE:
736
case VT_STORED_OBJECT:
737
if (pvar->pStream)
738
IStream_Release(pvar->pStream);
739
break;
740
case VT_CLSID:
741
case VT_LPSTR:
742
case VT_LPWSTR:
743
/* pick an arbitrary typed pointer - we don't care about the type
744
* as we are just freeing it */
745
CoTaskMemFree(pvar->puuid);
746
break;
747
case VT_BLOB:
748
case VT_BLOB_OBJECT:
749
CoTaskMemFree(pvar->blob.pBlobData);
750
break;
751
case VT_BSTR:
752
SysFreeString(pvar->bstrVal);
753
break;
754
case VT_CF:
755
if (pvar->pclipdata)
756
{
757
propvar_free_cf_array(1, pvar->pclipdata);
758
CoTaskMemFree(pvar->pclipdata);
759
}
760
break;
761
default:
762
if (pvar->vt & VT_VECTOR)
763
{
764
ULONG i;
765
766
switch (pvar->vt & ~VT_VECTOR)
767
{
768
case VT_VARIANT:
769
FreePropVariantArray(pvar->capropvar.cElems, pvar->capropvar.pElems);
770
break;
771
case VT_CF:
772
propvar_free_cf_array(pvar->caclipdata.cElems, pvar->caclipdata.pElems);
773
break;
774
case VT_BSTR:
775
for (i = 0; i < pvar->cabstr.cElems; i++)
776
SysFreeString(pvar->cabstr.pElems[i]);
777
break;
778
case VT_LPSTR:
779
for (i = 0; i < pvar->calpstr.cElems; i++)
780
CoTaskMemFree(pvar->calpstr.pElems[i]);
781
break;
782
case VT_LPWSTR:
783
for (i = 0; i < pvar->calpwstr.cElems; i++)
784
CoTaskMemFree(pvar->calpwstr.pElems[i]);
785
break;
786
}
787
if (pvar->vt & ~VT_VECTOR)
788
{
789
/* pick an arbitrary VT_VECTOR structure - they all have the same
790
* memory layout */
791
CoTaskMemFree(pvar->capropvar.pElems);
792
}
793
}
794
else if (pvar->vt & VT_ARRAY)
795
hr = SafeArrayDestroy(pvar->parray);
796
else
797
{
798
WARN("Invalid/unsupported type %d\n", pvar->vt);
799
hr = STG_E_INVALIDPARAMETER;
800
}
801
}
802
803
memset(pvar, 0, sizeof(*pvar));
804
return hr;
805
}
806
807
/***********************************************************************
808
* PropVariantCopy (combase.@)
809
*/
810
HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest, const PROPVARIANT *pvarSrc)
811
{
812
ULONG len;
813
HRESULT hr;
814
815
TRACE("%p, %p vt %04x.\n", pvarDest, pvarSrc, pvarSrc->vt);
816
817
hr = propvar_validatetype(pvarSrc->vt);
818
if (FAILED(hr))
819
return DISP_E_BADVARTYPE;
820
821
/* this will deal with most cases */
822
*pvarDest = *pvarSrc;
823
824
switch (pvarSrc->vt)
825
{
826
case VT_EMPTY:
827
case VT_NULL:
828
case VT_I1:
829
case VT_UI1:
830
case VT_I2:
831
case VT_UI2:
832
case VT_BOOL:
833
case VT_DECIMAL:
834
case VT_I4:
835
case VT_UI4:
836
case VT_R4:
837
case VT_ERROR:
838
case VT_I8:
839
case VT_UI8:
840
case VT_INT:
841
case VT_UINT:
842
case VT_R8:
843
case VT_CY:
844
case VT_DATE:
845
case VT_FILETIME:
846
break;
847
case VT_DISPATCH:
848
case VT_UNKNOWN:
849
case VT_STREAM:
850
case VT_STREAMED_OBJECT:
851
case VT_STORAGE:
852
case VT_STORED_OBJECT:
853
if (pvarDest->pStream)
854
IStream_AddRef(pvarDest->pStream);
855
break;
856
case VT_CLSID:
857
pvarDest->puuid = CoTaskMemAlloc(sizeof(CLSID));
858
*pvarDest->puuid = *pvarSrc->puuid;
859
break;
860
case VT_LPSTR:
861
if (pvarSrc->pszVal)
862
{
863
len = strlen(pvarSrc->pszVal);
864
pvarDest->pszVal = CoTaskMemAlloc((len+1)*sizeof(CHAR));
865
CopyMemory(pvarDest->pszVal, pvarSrc->pszVal, (len+1)*sizeof(CHAR));
866
}
867
break;
868
case VT_LPWSTR:
869
if (pvarSrc->pwszVal)
870
{
871
len = lstrlenW(pvarSrc->pwszVal);
872
pvarDest->pwszVal = CoTaskMemAlloc((len+1)*sizeof(WCHAR));
873
CopyMemory(pvarDest->pwszVal, pvarSrc->pwszVal, (len+1)*sizeof(WCHAR));
874
}
875
break;
876
case VT_BLOB:
877
case VT_BLOB_OBJECT:
878
if (pvarSrc->blob.pBlobData)
879
{
880
len = pvarSrc->blob.cbSize;
881
pvarDest->blob.pBlobData = CoTaskMemAlloc(len);
882
CopyMemory(pvarDest->blob.pBlobData, pvarSrc->blob.pBlobData, len);
883
}
884
break;
885
case VT_BSTR:
886
pvarDest->bstrVal = SysAllocString(pvarSrc->bstrVal);
887
break;
888
case VT_CF:
889
if (pvarSrc->pclipdata)
890
{
891
len = pvarSrc->pclipdata->cbSize - sizeof(pvarSrc->pclipdata->ulClipFmt);
892
pvarDest->pclipdata = CoTaskMemAlloc(sizeof (CLIPDATA));
893
pvarDest->pclipdata->cbSize = pvarSrc->pclipdata->cbSize;
894
pvarDest->pclipdata->ulClipFmt = pvarSrc->pclipdata->ulClipFmt;
895
pvarDest->pclipdata->pClipData = CoTaskMemAlloc(len);
896
CopyMemory(pvarDest->pclipdata->pClipData, pvarSrc->pclipdata->pClipData, len);
897
}
898
break;
899
default:
900
if (pvarSrc->vt & VT_VECTOR)
901
{
902
int elemSize;
903
ULONG i;
904
905
switch (pvarSrc->vt & ~VT_VECTOR)
906
{
907
case VT_I1: elemSize = sizeof(pvarSrc->cVal); break;
908
case VT_UI1: elemSize = sizeof(pvarSrc->bVal); break;
909
case VT_I2: elemSize = sizeof(pvarSrc->iVal); break;
910
case VT_UI2: elemSize = sizeof(pvarSrc->uiVal); break;
911
case VT_BOOL: elemSize = sizeof(pvarSrc->boolVal); break;
912
case VT_I4: elemSize = sizeof(pvarSrc->lVal); break;
913
case VT_UI4: elemSize = sizeof(pvarSrc->ulVal); break;
914
case VT_R4: elemSize = sizeof(pvarSrc->fltVal); break;
915
case VT_R8: elemSize = sizeof(pvarSrc->dblVal); break;
916
case VT_ERROR: elemSize = sizeof(pvarSrc->scode); break;
917
case VT_I8: elemSize = sizeof(pvarSrc->hVal); break;
918
case VT_UI8: elemSize = sizeof(pvarSrc->uhVal); break;
919
case VT_CY: elemSize = sizeof(pvarSrc->cyVal); break;
920
case VT_DATE: elemSize = sizeof(pvarSrc->date); break;
921
case VT_FILETIME: elemSize = sizeof(pvarSrc->filetime); break;
922
case VT_CLSID: elemSize = sizeof(*pvarSrc->puuid); break;
923
case VT_CF: elemSize = sizeof(*pvarSrc->pclipdata); break;
924
case VT_BSTR: elemSize = sizeof(pvarSrc->bstrVal); break;
925
case VT_LPSTR: elemSize = sizeof(pvarSrc->pszVal); break;
926
case VT_LPWSTR: elemSize = sizeof(pvarSrc->pwszVal); break;
927
case VT_VARIANT: elemSize = sizeof(*pvarSrc->pvarVal); break;
928
929
default:
930
FIXME("Invalid element type: %ul\n", pvarSrc->vt & ~VT_VECTOR);
931
return E_INVALIDARG;
932
}
933
len = pvarSrc->capropvar.cElems;
934
pvarDest->capropvar.pElems = len ? CoTaskMemAlloc(len * elemSize) : NULL;
935
if (pvarSrc->vt == (VT_VECTOR | VT_VARIANT))
936
{
937
for (i = 0; i < len; i++)
938
PropVariantCopy(&pvarDest->capropvar.pElems[i], &pvarSrc->capropvar.pElems[i]);
939
}
940
else if (pvarSrc->vt == (VT_VECTOR | VT_CF))
941
{
942
FIXME("Copy clipformats\n");
943
}
944
else if (pvarSrc->vt == (VT_VECTOR | VT_BSTR))
945
{
946
for (i = 0; i < len; i++)
947
pvarDest->cabstr.pElems[i] = SysAllocString(pvarSrc->cabstr.pElems[i]);
948
}
949
else if (pvarSrc->vt == (VT_VECTOR | VT_LPSTR))
950
{
951
size_t strLen;
952
for (i = 0; i < len; i++)
953
{
954
strLen = lstrlenA(pvarSrc->calpstr.pElems[i]) + 1;
955
pvarDest->calpstr.pElems[i] = CoTaskMemAlloc(strLen);
956
memcpy(pvarDest->calpstr.pElems[i],
957
pvarSrc->calpstr.pElems[i], strLen);
958
}
959
}
960
else if (pvarSrc->vt == (VT_VECTOR | VT_LPWSTR))
961
{
962
size_t strLen;
963
for (i = 0; i < len; i++)
964
{
965
strLen = (lstrlenW(pvarSrc->calpwstr.pElems[i]) + 1) *
966
sizeof(WCHAR);
967
pvarDest->calpstr.pElems[i] = CoTaskMemAlloc(strLen);
968
memcpy(pvarDest->calpstr.pElems[i],
969
pvarSrc->calpstr.pElems[i], strLen);
970
}
971
}
972
else
973
CopyMemory(pvarDest->capropvar.pElems, pvarSrc->capropvar.pElems, len * elemSize);
974
}
975
else if (pvarSrc->vt & VT_ARRAY)
976
{
977
pvarDest->uhVal.QuadPart = 0;
978
return SafeArrayCopy(pvarSrc->parray, &pvarDest->parray);
979
}
980
else
981
WARN("Invalid/unsupported type %d\n", pvarSrc->vt);
982
}
983
984
return S_OK;
985
}
986
987
/***********************************************************************
988
* CoFileTimeNow (combase.@)
989
*/
990
HRESULT WINAPI CoFileTimeNow(FILETIME *filetime)
991
{
992
GetSystemTimeAsFileTime(filetime);
993
return S_OK;
994
}
995
996
/******************************************************************************
997
* CoCreateGuid (combase.@)
998
*/
999
HRESULT WINAPI CoCreateGuid(GUID *guid)
1000
{
1001
RPC_STATUS status;
1002
1003
if (!guid) return E_INVALIDARG;
1004
1005
status = UuidCreate(guid);
1006
if (status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY) return S_OK;
1007
return HRESULT_FROM_WIN32(status);
1008
}
1009
1010
/******************************************************************************
1011
* CoQueryProxyBlanket (combase.@)
1012
*/
1013
HRESULT WINAPI CoQueryProxyBlanket(IUnknown *proxy, DWORD *authn_service,
1014
DWORD *authz_service, OLECHAR **servername, DWORD *authn_level,
1015
DWORD *imp_level, void **auth_info, DWORD *capabilities)
1016
{
1017
IClientSecurity *client_security;
1018
HRESULT hr;
1019
1020
TRACE("%p, %p, %p, %p, %p, %p, %p, %p.\n", proxy, authn_service, authz_service, servername, authn_level, imp_level,
1021
auth_info, capabilities);
1022
1023
hr = IUnknown_QueryInterface(proxy, &IID_IClientSecurity, (void **)&client_security);
1024
if (SUCCEEDED(hr))
1025
{
1026
hr = IClientSecurity_QueryBlanket(client_security, proxy, authn_service, authz_service, servername,
1027
authn_level, imp_level, auth_info, capabilities);
1028
IClientSecurity_Release(client_security);
1029
}
1030
1031
if (FAILED(hr)) ERR("-- failed with %#lx.\n", hr);
1032
return hr;
1033
}
1034
1035
/******************************************************************************
1036
* CoSetProxyBlanket (combase.@)
1037
*/
1038
HRESULT WINAPI CoSetProxyBlanket(IUnknown *proxy, DWORD authn_service, DWORD authz_service,
1039
OLECHAR *servername, DWORD authn_level, DWORD imp_level, void *auth_info, DWORD capabilities)
1040
{
1041
IClientSecurity *client_security;
1042
HRESULT hr;
1043
1044
TRACE("%p, %lu, %lu, %p, %lu, %lu, %p, %#lx.\n", proxy, authn_service, authz_service, servername,
1045
authn_level, imp_level, auth_info, capabilities);
1046
1047
hr = IUnknown_QueryInterface(proxy, &IID_IClientSecurity, (void **)&client_security);
1048
if (SUCCEEDED(hr))
1049
{
1050
hr = IClientSecurity_SetBlanket(client_security, proxy, authn_service, authz_service, servername, authn_level,
1051
imp_level, auth_info, capabilities);
1052
IClientSecurity_Release(client_security);
1053
}
1054
1055
if (FAILED(hr)) ERR("-- failed with %#lx.\n", hr);
1056
return hr;
1057
}
1058
1059
/***********************************************************************
1060
* CoCopyProxy (combase.@)
1061
*/
1062
HRESULT WINAPI CoCopyProxy(IUnknown *proxy, IUnknown **proxy_copy)
1063
{
1064
IClientSecurity *client_security;
1065
HRESULT hr;
1066
1067
TRACE("%p, %p.\n", proxy, proxy_copy);
1068
1069
hr = IUnknown_QueryInterface(proxy, &IID_IClientSecurity, (void **)&client_security);
1070
if (SUCCEEDED(hr))
1071
{
1072
hr = IClientSecurity_CopyProxy(client_security, proxy, proxy_copy);
1073
IClientSecurity_Release(client_security);
1074
}
1075
1076
if (FAILED(hr)) ERR("-- failed with %#lx.\n", hr);
1077
return hr;
1078
}
1079
1080
/***********************************************************************
1081
* CoQueryClientBlanket (combase.@)
1082
*/
1083
HRESULT WINAPI CoQueryClientBlanket(DWORD *authn_service, DWORD *authz_service, OLECHAR **servername,
1084
DWORD *authn_level, DWORD *imp_level, RPC_AUTHZ_HANDLE *privs, DWORD *capabilities)
1085
{
1086
IServerSecurity *server_security;
1087
HRESULT hr;
1088
1089
TRACE("%p, %p, %p, %p, %p, %p, %p.\n", authn_service, authz_service, servername, authn_level, imp_level,
1090
privs, capabilities);
1091
1092
hr = CoGetCallContext(&IID_IServerSecurity, (void **)&server_security);
1093
if (SUCCEEDED(hr))
1094
{
1095
hr = IServerSecurity_QueryBlanket(server_security, authn_service, authz_service, servername, authn_level,
1096
imp_level, privs, capabilities);
1097
IServerSecurity_Release(server_security);
1098
}
1099
1100
return hr;
1101
}
1102
1103
/***********************************************************************
1104
* CoImpersonateClient (combase.@)
1105
*/
1106
HRESULT WINAPI CoImpersonateClient(void)
1107
{
1108
IServerSecurity *server_security;
1109
HRESULT hr;
1110
1111
TRACE("\n");
1112
1113
hr = CoGetCallContext(&IID_IServerSecurity, (void **)&server_security);
1114
if (SUCCEEDED(hr))
1115
{
1116
hr = IServerSecurity_ImpersonateClient(server_security);
1117
IServerSecurity_Release(server_security);
1118
}
1119
1120
return hr;
1121
}
1122
1123
/***********************************************************************
1124
* CoRevertToSelf (combase.@)
1125
*/
1126
HRESULT WINAPI CoRevertToSelf(void)
1127
{
1128
IServerSecurity *server_security;
1129
HRESULT hr;
1130
1131
TRACE("\n");
1132
1133
hr = CoGetCallContext(&IID_IServerSecurity, (void **)&server_security);
1134
if (SUCCEEDED(hr))
1135
{
1136
hr = IServerSecurity_RevertToSelf(server_security);
1137
IServerSecurity_Release(server_security);
1138
}
1139
1140
return hr;
1141
}
1142
1143
/***********************************************************************
1144
* CoInitializeSecurity (combase.@)
1145
*/
1146
HRESULT WINAPI CoInitializeSecurity(PSECURITY_DESCRIPTOR sd, LONG cAuthSvc,
1147
SOLE_AUTHENTICATION_SERVICE *asAuthSvc, void *reserved1, DWORD authn_level,
1148
DWORD imp_level, void *reserved2, DWORD capabilities, void *reserved3)
1149
{
1150
FIXME("%p, %ld, %p, %p, %ld, %ld, %p, %ld, %p stub\n", sd, cAuthSvc, asAuthSvc, reserved1, authn_level,
1151
imp_level, reserved2, capabilities, reserved3);
1152
1153
return S_OK;
1154
}
1155
1156
/***********************************************************************
1157
* CoGetObjectContext (combase.@)
1158
*/
1159
HRESULT WINAPI CoGetObjectContext(REFIID riid, void **ppv)
1160
{
1161
IObjContext *context;
1162
HRESULT hr;
1163
1164
TRACE("%s, %p.\n", debugstr_guid(riid), ppv);
1165
1166
*ppv = NULL;
1167
hr = CoGetContextToken((ULONG_PTR *)&context);
1168
if (FAILED(hr))
1169
return hr;
1170
1171
return IObjContext_QueryInterface(context, riid, ppv);
1172
}
1173
1174
/***********************************************************************
1175
* CoGetDefaultContext (combase.@)
1176
*/
1177
HRESULT WINAPI CoGetDefaultContext(APTTYPE type, REFIID riid, void **obj)
1178
{
1179
FIXME("%d, %s, %p stub\n", type, debugstr_guid(riid), obj);
1180
1181
return E_NOINTERFACE;
1182
}
1183
1184
/***********************************************************************
1185
* CoGetCallState (combase.@)
1186
*/
1187
HRESULT WINAPI CoGetCallState(int arg1, ULONG *arg2)
1188
{
1189
FIXME("%d, %p.\n", arg1, arg2);
1190
1191
return E_NOTIMPL;
1192
}
1193
1194
/***********************************************************************
1195
* CoGetActivationState (combase.@)
1196
*/
1197
HRESULT WINAPI CoGetActivationState(GUID guid, DWORD arg2, DWORD *arg3)
1198
{
1199
FIXME("%s, %lx, %p.\n", debugstr_guid(&guid), arg2, arg3);
1200
1201
return E_NOTIMPL;
1202
}
1203
1204
/******************************************************************************
1205
* CoGetTreatAsClass (combase.@)
1206
*/
1207
HRESULT WINAPI CoGetTreatAsClass(REFCLSID clsidOld, CLSID *clsidNew)
1208
{
1209
WCHAR buffW[CHARS_IN_GUID];
1210
LONG len = sizeof(buffW);
1211
HRESULT hr = S_OK;
1212
HKEY hkey = NULL;
1213
1214
TRACE("%s, %p.\n", debugstr_guid(clsidOld), clsidNew);
1215
1216
if (!clsidOld || !clsidNew)
1217
return E_INVALIDARG;
1218
1219
*clsidNew = *clsidOld;
1220
1221
hr = open_key_for_clsid(clsidOld, L"TreatAs", KEY_READ, &hkey);
1222
if (FAILED(hr))
1223
{
1224
hr = S_FALSE;
1225
goto done;
1226
}
1227
1228
if (RegQueryValueW(hkey, NULL, buffW, &len))
1229
{
1230
hr = S_FALSE;
1231
goto done;
1232
}
1233
1234
hr = CLSIDFromString(buffW, clsidNew);
1235
if (FAILED(hr))
1236
ERR("Failed to get CLSID from string %s, hr %#lx.\n", debugstr_w(buffW), hr);
1237
done:
1238
if (hkey) RegCloseKey(hkey);
1239
return hr;
1240
}
1241
1242
/******************************************************************************
1243
* CoTreatAsClass (combase.@)
1244
*/
1245
HRESULT WINAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew)
1246
{
1247
WCHAR clsidW[CHARS_IN_GUID];
1248
HKEY hkey = NULL;
1249
HRESULT hr;
1250
LONG size;
1251
CLSID id;
1252
1253
if (!clsidOld || !clsidNew)
1254
return E_INVALIDARG;
1255
1256
if (FAILED(hr = open_key_for_clsid(clsidOld, NULL, KEY_READ | KEY_WRITE, &hkey)))
1257
return hr;
1258
1259
if (IsEqualGUID( clsidOld, clsidNew ))
1260
{
1261
size = sizeof(clsidW);
1262
if (!RegQueryValueW(hkey, L"AutoTreatAs", clsidW, &size) && CLSIDFromString(clsidW, &id) == S_OK)
1263
{
1264
if (RegSetValueW(hkey, L"TreatAs", REG_SZ, clsidW, sizeof(clsidW)))
1265
{
1266
hr = REGDB_E_WRITEREGDB;
1267
goto done;
1268
}
1269
}
1270
else
1271
{
1272
if (RegDeleteKeyW(hkey, L"TreatAs"))
1273
hr = REGDB_E_WRITEREGDB;
1274
goto done;
1275
}
1276
}
1277
else
1278
{
1279
if (IsEqualGUID(clsidNew, &CLSID_NULL))
1280
{
1281
RegDeleteKeyW(hkey, L"TreatAs");
1282
}
1283
else
1284
{
1285
StringFromGUID2(clsidNew, clsidW, ARRAY_SIZE(clsidW));
1286
if (RegSetValueW(hkey, L"TreatAs", REG_SZ, clsidW, sizeof(clsidW)) != ERROR_SUCCESS)
1287
{
1288
WARN("RegSetValue failed\n");
1289
hr = REGDB_E_WRITEREGDB;
1290
goto done;
1291
}
1292
}
1293
}
1294
1295
done:
1296
if (hkey) RegCloseKey(hkey);
1297
return hr;
1298
}
1299
1300
/******************************************************************************
1301
* ProgIDFromCLSID (combase.@)
1302
*/
1303
HRESULT WINAPI DECLSPEC_HOTPATCH ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *progid)
1304
{
1305
ACTCTX_SECTION_KEYED_DATA data;
1306
LONG progidlen = 0;
1307
HKEY hkey;
1308
REGSAM opposite = (sizeof(void *) > sizeof(int)) ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
1309
BOOL is_wow64;
1310
HRESULT hr;
1311
1312
if (!progid)
1313
return E_INVALIDARG;
1314
1315
*progid = NULL;
1316
1317
data.cbSize = sizeof(data);
1318
if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,
1319
clsid, &data))
1320
{
1321
struct comclassredirect_data *comclass = (struct comclassredirect_data *)data.lpData;
1322
if (comclass->progid_len)
1323
{
1324
WCHAR *ptrW;
1325
1326
*progid = CoTaskMemAlloc(comclass->progid_len + sizeof(WCHAR));
1327
if (!*progid) return E_OUTOFMEMORY;
1328
1329
ptrW = (WCHAR *)((BYTE *)comclass + comclass->progid_offset);
1330
memcpy(*progid, ptrW, comclass->progid_len + sizeof(WCHAR));
1331
return S_OK;
1332
}
1333
else
1334
return REGDB_E_CLASSNOTREG;
1335
}
1336
1337
hr = open_key_for_clsid(clsid, L"ProgID", KEY_READ, &hkey);
1338
if (FAILED(hr) && (opposite == KEY_WOW64_32KEY || (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
1339
{
1340
hr = open_key_for_clsid(clsid, L"ProgID", opposite | KEY_READ, &hkey);
1341
if (FAILED(hr))
1342
return hr;
1343
}
1344
1345
if (RegQueryValueW(hkey, NULL, NULL, &progidlen))
1346
hr = REGDB_E_CLASSNOTREG;
1347
1348
if (hr == S_OK)
1349
{
1350
*progid = CoTaskMemAlloc(progidlen * sizeof(WCHAR));
1351
if (*progid)
1352
{
1353
if (RegQueryValueW(hkey, NULL, *progid, &progidlen))
1354
{
1355
hr = REGDB_E_CLASSNOTREG;
1356
CoTaskMemFree(*progid);
1357
*progid = NULL;
1358
}
1359
}
1360
else
1361
hr = E_OUTOFMEMORY;
1362
}
1363
1364
RegCloseKey(hkey);
1365
return hr;
1366
}
1367
1368
static inline BOOL is_valid_hex(WCHAR c)
1369
{
1370
if (!(((c >= '0') && (c <= '9')) ||
1371
((c >= 'a') && (c <= 'f')) ||
1372
((c >= 'A') && (c <= 'F'))))
1373
return FALSE;
1374
return TRUE;
1375
}
1376
1377
static const BYTE guid_conv_table[256] =
1378
{
1379
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
1380
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
1381
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
1382
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
1383
0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
1384
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
1385
0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
1386
};
1387
1388
static BOOL guid_from_string(LPCWSTR s, GUID *id)
1389
{
1390
int i;
1391
1392
if (!s || s[0] != '{')
1393
{
1394
memset(id, 0, sizeof(*id));
1395
if (!s) return TRUE;
1396
return FALSE;
1397
}
1398
1399
TRACE("%s -> %p\n", debugstr_w(s), id);
1400
1401
/* In form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
1402
1403
id->Data1 = 0;
1404
for (i = 1; i < 9; ++i)
1405
{
1406
if (!is_valid_hex(s[i])) return FALSE;
1407
id->Data1 = (id->Data1 << 4) | guid_conv_table[s[i]];
1408
}
1409
if (s[9] != '-') return FALSE;
1410
1411
id->Data2 = 0;
1412
for (i = 10; i < 14; ++i)
1413
{
1414
if (!is_valid_hex(s[i])) return FALSE;
1415
id->Data2 = (id->Data2 << 4) | guid_conv_table[s[i]];
1416
}
1417
if (s[14] != '-') return FALSE;
1418
1419
id->Data3 = 0;
1420
for (i = 15; i < 19; ++i)
1421
{
1422
if (!is_valid_hex(s[i])) return FALSE;
1423
id->Data3 = (id->Data3 << 4) | guid_conv_table[s[i]];
1424
}
1425
if (s[19] != '-') return FALSE;
1426
1427
for (i = 20; i < 37; i += 2)
1428
{
1429
if (i == 24)
1430
{
1431
if (s[i] != '-') return FALSE;
1432
i++;
1433
}
1434
if (!is_valid_hex(s[i]) || !is_valid_hex(s[i + 1])) return FALSE;
1435
id->Data4[(i - 20) / 2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i + 1]];
1436
}
1437
1438
if (s[37] == '}' && s[38] == '\0')
1439
return TRUE;
1440
1441
return FALSE;
1442
}
1443
1444
static HRESULT clsid_from_string_reg(LPCOLESTR progid, CLSID *clsid)
1445
{
1446
WCHAR buf2[CHARS_IN_GUID];
1447
LONG buf2len = sizeof(buf2);
1448
HKEY xhkey;
1449
WCHAR *buf;
1450
1451
memset(clsid, 0, sizeof(*clsid));
1452
buf = malloc((lstrlenW(progid) + 8) * sizeof(WCHAR));
1453
if (!buf) return E_OUTOFMEMORY;
1454
1455
lstrcpyW(buf, progid);
1456
lstrcatW(buf, L"\\CLSID");
1457
if (open_classes_key(HKEY_CLASSES_ROOT, buf, MAXIMUM_ALLOWED, &xhkey))
1458
{
1459
free(buf);
1460
WARN("couldn't open key for ProgID %s\n", debugstr_w(progid));
1461
return CO_E_CLASSSTRING;
1462
}
1463
free(buf);
1464
1465
if (RegQueryValueW(xhkey, NULL, buf2, &buf2len))
1466
{
1467
RegCloseKey(xhkey);
1468
WARN("couldn't query clsid value for ProgID %s\n", debugstr_w(progid));
1469
return CO_E_CLASSSTRING;
1470
}
1471
RegCloseKey(xhkey);
1472
return guid_from_string(buf2, clsid) ? S_OK : CO_E_CLASSSTRING;
1473
}
1474
1475
/******************************************************************************
1476
* CLSIDFromProgID (combase.@)
1477
*/
1478
HRESULT WINAPI DECLSPEC_HOTPATCH CLSIDFromProgID(LPCOLESTR progid, CLSID *clsid)
1479
{
1480
ACTCTX_SECTION_KEYED_DATA data;
1481
1482
if (!progid || !clsid)
1483
return E_INVALIDARG;
1484
1485
data.cbSize = sizeof(data);
1486
if (FindActCtxSectionStringW(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION,
1487
progid, &data))
1488
{
1489
struct progidredirect_data *progiddata = (struct progidredirect_data *)data.lpData;
1490
CLSID *alias = (CLSID *)((BYTE *)data.lpSectionBase + progiddata->clsid_offset);
1491
*clsid = *alias;
1492
return S_OK;
1493
}
1494
1495
return clsid_from_string_reg(progid, clsid);
1496
}
1497
1498
/******************************************************************************
1499
* CLSIDFromProgIDEx (combase.@)
1500
*/
1501
HRESULT WINAPI CLSIDFromProgIDEx(LPCOLESTR progid, CLSID *clsid)
1502
{
1503
FIXME("%s, %p: semi-stub\n", debugstr_w(progid), clsid);
1504
1505
return CLSIDFromProgID(progid, clsid);
1506
}
1507
1508
/******************************************************************************
1509
* CLSIDFromString (combase.@)
1510
*/
1511
HRESULT WINAPI CLSIDFromString(LPCOLESTR str, LPCLSID clsid)
1512
{
1513
CLSID tmp_id;
1514
HRESULT hr;
1515
1516
if (!clsid)
1517
return E_INVALIDARG;
1518
1519
if (guid_from_string(str, clsid))
1520
return S_OK;
1521
1522
/* It appears a ProgID is also valid */
1523
hr = clsid_from_string_reg(str, &tmp_id);
1524
if (SUCCEEDED(hr))
1525
*clsid = tmp_id;
1526
1527
return hr;
1528
}
1529
1530
/******************************************************************************
1531
* IIDFromString (combase.@)
1532
*/
1533
HRESULT WINAPI IIDFromString(LPCOLESTR str, IID *iid)
1534
{
1535
TRACE("%s, %p\n", debugstr_w(str), iid);
1536
1537
if (!str)
1538
{
1539
memset(iid, 0, sizeof(*iid));
1540
return S_OK;
1541
}
1542
1543
/* length mismatch is a special case */
1544
if (lstrlenW(str) + 1 != CHARS_IN_GUID)
1545
return E_INVALIDARG;
1546
1547
if (str[0] != '{')
1548
return CO_E_IIDSTRING;
1549
1550
return guid_from_string(str, iid) ? S_OK : CO_E_IIDSTRING;
1551
}
1552
1553
/******************************************************************************
1554
* StringFromCLSID (combase.@)
1555
*/
1556
HRESULT WINAPI StringFromCLSID(REFCLSID clsid, LPOLESTR *str)
1557
{
1558
if (!(*str = CoTaskMemAlloc(CHARS_IN_GUID * sizeof(WCHAR)))) return E_OUTOFMEMORY;
1559
StringFromGUID2(clsid, *str, CHARS_IN_GUID);
1560
return S_OK;
1561
}
1562
1563
/******************************************************************************
1564
* StringFromGUID2 (combase.@)
1565
*/
1566
INT WINAPI StringFromGUID2(REFGUID guid, LPOLESTR str, INT cmax)
1567
{
1568
if (!guid || cmax < CHARS_IN_GUID) return 0;
1569
swprintf(str, CHARS_IN_GUID, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", guid->Data1,
1570
guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
1571
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
1572
return CHARS_IN_GUID;
1573
}
1574
1575
static void init_multi_qi(DWORD count, MULTI_QI *mqi, HRESULT hr)
1576
{
1577
ULONG i;
1578
1579
for (i = 0; i < count; i++)
1580
{
1581
mqi[i].pItf = NULL;
1582
mqi[i].hr = hr;
1583
}
1584
}
1585
1586
static HRESULT return_multi_qi(IUnknown *unk, DWORD count, MULTI_QI *mqi, BOOL include_unk)
1587
{
1588
ULONG index = 0, fetched = 0;
1589
1590
if (include_unk)
1591
{
1592
mqi[0].hr = S_OK;
1593
mqi[0].pItf = unk;
1594
index = fetched = 1;
1595
}
1596
1597
for (; index < count; index++)
1598
{
1599
mqi[index].hr = IUnknown_QueryInterface(unk, mqi[index].pIID, (void **)&mqi[index].pItf);
1600
if (mqi[index].hr == S_OK)
1601
fetched++;
1602
}
1603
1604
if (!include_unk)
1605
IUnknown_Release(unk);
1606
1607
if (fetched == 0)
1608
return E_NOINTERFACE;
1609
1610
return fetched == count ? S_OK : CO_S_NOTALLINTERFACES;
1611
}
1612
1613
/***********************************************************************
1614
* CoGetInstanceFromFile (combase.@)
1615
*/
1616
HRESULT WINAPI DECLSPEC_HOTPATCH CoGetInstanceFromFile(COSERVERINFO *server_info, CLSID *rclsid,
1617
IUnknown *outer, DWORD cls_context, DWORD grfmode, OLECHAR *filename, DWORD count,
1618
MULTI_QI *results)
1619
{
1620
IPersistFile *pf = NULL;
1621
IUnknown *obj = NULL;
1622
CLSID clsid;
1623
HRESULT hr;
1624
1625
if (!count || !results)
1626
return E_INVALIDARG;
1627
1628
if (server_info)
1629
FIXME("() non-NULL server_info not supported\n");
1630
1631
init_multi_qi(count, results, E_NOINTERFACE);
1632
1633
if (!rclsid)
1634
{
1635
hr = GetClassFile(filename, &clsid);
1636
if (FAILED(hr))
1637
{
1638
ERR("Failed to get CLSID from a file.\n");
1639
return hr;
1640
}
1641
1642
rclsid = &clsid;
1643
}
1644
1645
hr = CoCreateInstance(rclsid, outer, cls_context, &IID_IUnknown, (void **)&obj);
1646
if (hr != S_OK)
1647
{
1648
init_multi_qi(count, results, hr);
1649
return hr;
1650
}
1651
1652
/* Init from file */
1653
hr = IUnknown_QueryInterface(obj, &IID_IPersistFile, (void **)&pf);
1654
if (FAILED(hr))
1655
{
1656
init_multi_qi(count, results, hr);
1657
IUnknown_Release(obj);
1658
return hr;
1659
}
1660
1661
hr = IPersistFile_Load(pf, filename, grfmode);
1662
IPersistFile_Release(pf);
1663
if (SUCCEEDED(hr))
1664
return return_multi_qi(obj, count, results, FALSE);
1665
else
1666
{
1667
init_multi_qi(count, results, hr);
1668
IUnknown_Release(obj);
1669
return hr;
1670
}
1671
}
1672
1673
/***********************************************************************
1674
* CoGetInstanceFromIStorage (combase.@)
1675
*/
1676
HRESULT WINAPI CoGetInstanceFromIStorage(COSERVERINFO *server_info, CLSID *rclsid,
1677
IUnknown *outer, DWORD cls_context, IStorage *storage, DWORD count, MULTI_QI *results)
1678
{
1679
IPersistStorage *ps = NULL;
1680
IUnknown *obj = NULL;
1681
STATSTG stat;
1682
HRESULT hr;
1683
1684
if (!count || !results || !storage)
1685
return E_INVALIDARG;
1686
1687
if (server_info)
1688
FIXME("() non-NULL server_info not supported\n");
1689
1690
init_multi_qi(count, results, E_NOINTERFACE);
1691
1692
if (!rclsid)
1693
{
1694
memset(&stat.clsid, 0, sizeof(stat.clsid));
1695
hr = IStorage_Stat(storage, &stat, STATFLAG_NONAME);
1696
if (FAILED(hr))
1697
{
1698
ERR("Failed to get CLSID from a storage.\n");
1699
return hr;
1700
}
1701
1702
rclsid = &stat.clsid;
1703
}
1704
1705
hr = CoCreateInstance(rclsid, outer, cls_context, &IID_IUnknown, (void **)&obj);
1706
if (hr != S_OK)
1707
return hr;
1708
1709
/* Init from IStorage */
1710
hr = IUnknown_QueryInterface(obj, &IID_IPersistStorage, (void **)&ps);
1711
if (FAILED(hr))
1712
ERR("failed to get IPersistStorage\n");
1713
1714
if (ps)
1715
{
1716
IPersistStorage_Load(ps, storage);
1717
IPersistStorage_Release(ps);
1718
}
1719
1720
return return_multi_qi(obj, count, results, FALSE);
1721
}
1722
1723
/***********************************************************************
1724
* CoCreateInstance (combase.@)
1725
*/
1726
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, IUnknown *outer, DWORD cls_context,
1727
REFIID riid, void **obj)
1728
{
1729
MULTI_QI multi_qi = { .pIID = riid };
1730
HRESULT hr;
1731
1732
TRACE("%s, %p, %#lx, %s, %p.\n", debugstr_guid(rclsid), outer, cls_context, debugstr_guid(riid), obj);
1733
1734
if (!obj)
1735
return E_POINTER;
1736
1737
hr = CoCreateInstanceEx(rclsid, outer, cls_context, NULL, 1, &multi_qi);
1738
*obj = multi_qi.pItf;
1739
return hr;
1740
}
1741
1742
/***********************************************************************
1743
* CoCreateInstanceFromApp (combase.@)
1744
*/
1745
HRESULT WINAPI CoCreateInstanceFromApp(REFCLSID rclsid, IUnknown *outer, DWORD cls_context,
1746
void *server_info, ULONG count, MULTI_QI *results)
1747
{
1748
TRACE("%s, %p, %#lx, %p, %lu, %p\n", debugstr_guid(rclsid), outer, cls_context, server_info,
1749
count, results);
1750
1751
return CoCreateInstanceEx(rclsid, outer, cls_context | CLSCTX_APPCONTAINER, server_info,
1752
count, results);
1753
}
1754
1755
static HRESULT com_get_class_object(REFCLSID rclsid, DWORD clscontext,
1756
COSERVERINFO *server_info, REFIID riid, void **obj)
1757
{
1758
struct class_reg_data clsreg = { 0 };
1759
HRESULT hr = E_UNEXPECTED;
1760
IUnknown *registered_obj;
1761
struct apartment *apt;
1762
1763
if (!obj)
1764
return E_INVALIDARG;
1765
1766
*obj = NULL;
1767
1768
if (!(apt = apartment_get_current_or_mta()))
1769
{
1770
ERR("apartment not initialised\n");
1771
return CO_E_NOTINITIALIZED;
1772
}
1773
1774
if (server_info)
1775
FIXME("server_info name %s, authinfo %p\n", debugstr_w(server_info->pwszName), server_info->pAuthInfo);
1776
1777
if (clscontext & CLSCTX_INPROC_SERVER)
1778
{
1779
if (IsEqualCLSID(rclsid, &CLSID_InProcFreeMarshaler) ||
1780
IsEqualCLSID(rclsid, &CLSID_GlobalOptions) ||
1781
(!(clscontext & CLSCTX_APPCONTAINER) && IsEqualCLSID(rclsid, &CLSID_ManualResetEvent)) ||
1782
IsEqualCLSID(rclsid, &CLSID_StdGlobalInterfaceTable))
1783
{
1784
apartment_release(apt);
1785
1786
if (IsEqualCLSID(rclsid, &CLSID_GlobalOptions))
1787
return get_builtin_class_factory(rclsid, riid, obj);
1788
else
1789
return Ole32DllGetClassObject(rclsid, riid, obj);
1790
}
1791
}
1792
1793
if (clscontext & CLSCTX_INPROC)
1794
{
1795
ACTCTX_SECTION_KEYED_DATA data;
1796
1797
data.cbSize = sizeof(data);
1798
/* search activation context first */
1799
if (FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
1800
ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, rclsid, &data))
1801
{
1802
struct comclassredirect_data *comclass = (struct comclassredirect_data *)data.lpData;
1803
1804
clsreg.u.actctx.module_name = (WCHAR *)((BYTE *)data.lpSectionBase + comclass->name_offset);
1805
clsreg.u.actctx.hactctx = data.hActCtx;
1806
clsreg.u.actctx.threading_model = comclass->model;
1807
clsreg.origin = CLASS_REG_ACTCTX;
1808
1809
hr = apartment_get_inproc_class_object(apt, &clsreg, &comclass->clsid, riid, clscontext, obj);
1810
ReleaseActCtx(data.hActCtx);
1811
apartment_release(apt);
1812
return hr;
1813
}
1814
}
1815
1816
/*
1817
* First, try and see if we can't match the class ID with one of the
1818
* registered classes.
1819
*/
1820
if (!(clscontext & CLSCTX_APPCONTAINER) && (registered_obj = com_get_registered_class_object(apt, rclsid, clscontext)))
1821
{
1822
hr = IUnknown_QueryInterface(registered_obj, riid, obj);
1823
IUnknown_Release(registered_obj);
1824
apartment_release(apt);
1825
return hr;
1826
}
1827
1828
/* First try in-process server */
1829
if (clscontext & CLSCTX_INPROC_SERVER)
1830
{
1831
HKEY hkey;
1832
1833
hr = open_key_for_clsid(rclsid, L"InprocServer32", KEY_READ, &hkey);
1834
if (FAILED(hr))
1835
{
1836
if (hr == REGDB_E_CLASSNOTREG)
1837
ERR("class %s not registered\n", debugstr_guid(rclsid));
1838
else if (hr == REGDB_E_KEYMISSING)
1839
{
1840
WARN("class %s not registered as in-proc server\n", debugstr_guid(rclsid));
1841
hr = REGDB_E_CLASSNOTREG;
1842
}
1843
}
1844
1845
if (SUCCEEDED(hr))
1846
{
1847
clsreg.u.hkey = hkey;
1848
clsreg.origin = CLASS_REG_REGISTRY;
1849
1850
hr = apartment_get_inproc_class_object(apt, &clsreg, rclsid, riid, clscontext, obj);
1851
RegCloseKey(hkey);
1852
}
1853
1854
/* return if we got a class, otherwise fall through to one of the
1855
* other types */
1856
if (SUCCEEDED(hr))
1857
{
1858
apartment_release(apt);
1859
return hr;
1860
}
1861
}
1862
1863
/* Next try in-process handler */
1864
if (clscontext & CLSCTX_INPROC_HANDLER)
1865
{
1866
HKEY hkey;
1867
1868
hr = open_key_for_clsid(rclsid, L"InprocHandler32", KEY_READ, &hkey);
1869
if (FAILED(hr))
1870
{
1871
if (hr == REGDB_E_CLASSNOTREG)
1872
ERR("class %s not registered\n", debugstr_guid(rclsid));
1873
else if (hr == REGDB_E_KEYMISSING)
1874
{
1875
WARN("class %s not registered in-proc handler\n", debugstr_guid(rclsid));
1876
hr = REGDB_E_CLASSNOTREG;
1877
}
1878
}
1879
1880
if (SUCCEEDED(hr))
1881
{
1882
clsreg.u.hkey = hkey;
1883
clsreg.origin = CLASS_REG_REGISTRY;
1884
1885
hr = apartment_get_inproc_class_object(apt, &clsreg, rclsid, riid, clscontext, obj);
1886
RegCloseKey(hkey);
1887
}
1888
1889
/* return if we got a class, otherwise fall through to one of the
1890
* other types */
1891
if (SUCCEEDED(hr))
1892
{
1893
apartment_release(apt);
1894
return hr;
1895
}
1896
}
1897
apartment_release(apt);
1898
1899
/* Next try out of process */
1900
if (clscontext & CLSCTX_LOCAL_SERVER)
1901
{
1902
hr = rpc_get_local_class_object(rclsid, riid, obj);
1903
if (SUCCEEDED(hr))
1904
return hr;
1905
}
1906
1907
/* Finally try remote: this requires networked DCOM (a lot of work) */
1908
if (clscontext & CLSCTX_REMOTE_SERVER)
1909
{
1910
FIXME ("CLSCTX_REMOTE_SERVER not supported\n");
1911
hr = REGDB_E_CLASSNOTREG;
1912
}
1913
1914
if (FAILED(hr))
1915
ERR("no class object %s could be created for context %#lx\n", debugstr_guid(rclsid), clscontext);
1916
1917
return hr;
1918
}
1919
1920
/***********************************************************************
1921
* CoCreateInstanceEx (combase.@)
1922
*/
1923
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstanceEx(REFCLSID rclsid, IUnknown *outer, DWORD cls_context,
1924
COSERVERINFO *server_info, ULONG count, MULTI_QI *results)
1925
{
1926
IClassFactory *factory;
1927
IUnknown *unk = NULL;
1928
CLSID clsid;
1929
HRESULT hr;
1930
1931
TRACE("%s, %p, %#lx, %p, %lu, %p\n", debugstr_guid(rclsid), outer, cls_context, server_info, count, results);
1932
1933
if (!count || !results)
1934
return E_INVALIDARG;
1935
1936
if (server_info)
1937
FIXME("Server info is not supported.\n");
1938
1939
init_multi_qi(count, results, E_NOINTERFACE);
1940
1941
clsid = *rclsid;
1942
if (!(cls_context & CLSCTX_APPCONTAINER))
1943
CoGetTreatAsClass(rclsid, &clsid);
1944
1945
if (FAILED(hr = com_get_class_object(&clsid, cls_context, NULL, &IID_IClassFactory, (void **)&factory)))
1946
return hr;
1947
1948
hr = IClassFactory_CreateInstance(factory, outer, results[0].pIID, (void **)&unk);
1949
IClassFactory_Release(factory);
1950
if (FAILED(hr))
1951
{
1952
if (hr == CLASS_E_NOAGGREGATION && outer)
1953
FIXME("Class %s does not support aggregation\n", debugstr_guid(&clsid));
1954
else
1955
FIXME("no instance created for interface %s of class %s, hr %#lx.\n",
1956
debugstr_guid(results[0].pIID), debugstr_guid(&clsid), hr);
1957
return hr;
1958
}
1959
1960
return return_multi_qi(unk, count, results, TRUE);
1961
}
1962
1963
/***********************************************************************
1964
* CoGetClassObject (combase.@)
1965
*/
1966
HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(REFCLSID rclsid, DWORD clscontext,
1967
COSERVERINFO *server_info, REFIID riid, void **obj)
1968
{
1969
TRACE("%s, %#lx, %s\n", debugstr_guid(rclsid), clscontext, debugstr_guid(riid));
1970
1971
return com_get_class_object(rclsid, clscontext, server_info, riid, obj);
1972
}
1973
1974
/***********************************************************************
1975
* CoFreeUnusedLibraries (combase.@)
1976
*/
1977
void WINAPI DECLSPEC_HOTPATCH CoFreeUnusedLibraries(void)
1978
{
1979
CoFreeUnusedLibrariesEx(INFINITE, 0);
1980
}
1981
1982
/***********************************************************************
1983
* CoGetCallContext (combase.@)
1984
*/
1985
HRESULT WINAPI CoGetCallContext(REFIID riid, void **obj)
1986
{
1987
struct tlsdata *tlsdata;
1988
HRESULT hr;
1989
1990
TRACE("%s, %p\n", debugstr_guid(riid), obj);
1991
1992
if (FAILED(hr = com_get_tlsdata(&tlsdata)))
1993
return hr;
1994
1995
if (!tlsdata->call_state)
1996
return RPC_E_CALL_COMPLETE;
1997
1998
return IUnknown_QueryInterface(tlsdata->call_state, riid, obj);
1999
}
2000
2001
/***********************************************************************
2002
* CoSwitchCallContext (combase.@)
2003
*/
2004
HRESULT WINAPI CoSwitchCallContext(IUnknown *context, IUnknown **old_context)
2005
{
2006
struct tlsdata *tlsdata;
2007
HRESULT hr;
2008
2009
TRACE("%p, %p\n", context, old_context);
2010
2011
if (FAILED(hr = com_get_tlsdata(&tlsdata)))
2012
return hr;
2013
2014
/* Reference counts are not touched. */
2015
*old_context = tlsdata->call_state;
2016
tlsdata->call_state = context;
2017
2018
return S_OK;
2019
}
2020
2021
/******************************************************************************
2022
* CoRegisterInitializeSpy (combase.@)
2023
*/
2024
HRESULT WINAPI CoRegisterInitializeSpy(IInitializeSpy *spy, ULARGE_INTEGER *cookie)
2025
{
2026
struct tlsdata *tlsdata;
2027
struct init_spy *entry;
2028
unsigned int id;
2029
HRESULT hr;
2030
2031
TRACE("%p, %p\n", spy, cookie);
2032
2033
if (!spy || !cookie)
2034
return E_INVALIDARG;
2035
2036
if (FAILED(hr = com_get_tlsdata(&tlsdata)))
2037
return hr;
2038
2039
hr = IInitializeSpy_QueryInterface(spy, &IID_IInitializeSpy, (void **)&spy);
2040
if (FAILED(hr))
2041
return hr;
2042
2043
entry = malloc(sizeof(*entry));
2044
if (!entry)
2045
{
2046
IInitializeSpy_Release(spy);
2047
return E_OUTOFMEMORY;
2048
}
2049
2050
entry->spy = spy;
2051
2052
id = 0;
2053
while (get_spy_entry(tlsdata, id) != NULL)
2054
{
2055
id++;
2056
}
2057
2058
entry->id = id;
2059
list_add_head(&tlsdata->spies, &entry->entry);
2060
2061
cookie->u.HighPart = GetCurrentThreadId();
2062
cookie->u.LowPart = entry->id;
2063
2064
return S_OK;
2065
}
2066
2067
/******************************************************************************
2068
* CoRevokeInitializeSpy (combase.@)
2069
*/
2070
HRESULT WINAPI CoRevokeInitializeSpy(ULARGE_INTEGER cookie)
2071
{
2072
struct tlsdata *tlsdata;
2073
struct init_spy *spy;
2074
HRESULT hr;
2075
2076
TRACE("%s\n", wine_dbgstr_longlong(cookie.QuadPart));
2077
2078
if (cookie.u.HighPart != GetCurrentThreadId())
2079
return E_INVALIDARG;
2080
2081
if (FAILED(hr = com_get_tlsdata(&tlsdata)))
2082
return hr;
2083
2084
if (!(spy = get_spy_entry(tlsdata, cookie.u.LowPart))) return E_INVALIDARG;
2085
2086
IInitializeSpy_Release(spy->spy);
2087
spy->spy = NULL;
2088
if (!tlsdata->spies_lock)
2089
{
2090
list_remove(&spy->entry);
2091
free(spy);
2092
}
2093
return S_OK;
2094
}
2095
2096
static BOOL com_peek_message(struct apartment *apt, MSG *msg)
2097
{
2098
/* First try to retrieve messages for incoming COM calls to the apartment window */
2099
return (apt->win && PeekMessageW(msg, apt->win, 0, 0, PM_REMOVE | PM_NOYIELD)) ||
2100
/* Next retrieve other messages necessary for the app to remain responsive */
2101
PeekMessageW(msg, NULL, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE | PM_NOYIELD) ||
2102
PeekMessageW(msg, NULL, 0, 0, PM_QS_PAINT | PM_QS_SENDMESSAGE | PM_REMOVE | PM_NOYIELD);
2103
}
2104
2105
/***********************************************************************
2106
* CoWaitForMultipleHandles (combase.@)
2107
*/
2108
HRESULT WINAPI CoWaitForMultipleHandles(DWORD flags, DWORD timeout, ULONG handle_count, HANDLE *handles,
2109
DWORD *index)
2110
{
2111
BOOL check_apc = !!(flags & COWAIT_ALERTABLE), message_loop;
2112
struct { BOOL post; UINT code; } quit = { .post = FALSE };
2113
DWORD start_time, wait_flags = 0;
2114
struct tlsdata *tlsdata;
2115
struct apartment *apt;
2116
HRESULT hr;
2117
2118
TRACE("%#lx, %#lx, %lu, %p, %p\n", flags, timeout, handle_count, handles, index);
2119
2120
if (!index)
2121
return E_INVALIDARG;
2122
2123
*index = 0;
2124
2125
if (!handles)
2126
return E_INVALIDARG;
2127
2128
if (!handle_count)
2129
return RPC_E_NO_SYNC;
2130
2131
if (FAILED(hr = com_get_tlsdata(&tlsdata)))
2132
return hr;
2133
2134
apt = com_get_current_apt();
2135
message_loop = apt && !apt->multi_threaded;
2136
2137
if (flags & COWAIT_WAITALL)
2138
wait_flags |= MWMO_WAITALL;
2139
if (flags & COWAIT_ALERTABLE)
2140
wait_flags |= MWMO_ALERTABLE;
2141
2142
start_time = GetTickCount();
2143
2144
while (TRUE)
2145
{
2146
DWORD now = GetTickCount(), res;
2147
2148
if (now - start_time > timeout)
2149
{
2150
hr = RPC_S_CALLPENDING;
2151
break;
2152
}
2153
2154
if (message_loop)
2155
{
2156
TRACE("waiting for rpc completion or window message\n");
2157
2158
res = WAIT_TIMEOUT;
2159
2160
if (check_apc)
2161
{
2162
res = WaitForMultipleObjectsEx(handle_count, handles, !!(flags & COWAIT_WAITALL), 0, TRUE);
2163
check_apc = FALSE;
2164
}
2165
2166
if (res == WAIT_TIMEOUT)
2167
res = MsgWaitForMultipleObjectsEx(handle_count, handles,
2168
timeout == INFINITE ? INFINITE : start_time + timeout - now,
2169
QS_SENDMESSAGE | QS_ALLPOSTMESSAGE | QS_PAINT, wait_flags);
2170
2171
if (res == WAIT_OBJECT_0 + handle_count) /* messages available */
2172
{
2173
int msg_count = 0;
2174
MSG msg;
2175
2176
/* call message filter */
2177
2178
if (apt->filter)
2179
{
2180
PENDINGTYPE pendingtype = tlsdata->pending_call_count_server ? PENDINGTYPE_NESTED : PENDINGTYPE_TOPLEVEL;
2181
DWORD be_handled = IMessageFilter_MessagePending(apt->filter, 0 /* FIXME */, now - start_time, pendingtype);
2182
2183
TRACE("IMessageFilter_MessagePending returned %ld\n", be_handled);
2184
2185
switch (be_handled)
2186
{
2187
case PENDINGMSG_CANCELCALL:
2188
WARN("call canceled\n");
2189
hr = RPC_E_CALL_CANCELED;
2190
break;
2191
case PENDINGMSG_WAITNOPROCESS:
2192
case PENDINGMSG_WAITDEFPROCESS:
2193
default:
2194
/* FIXME: MSDN is very vague about the difference
2195
* between WAITNOPROCESS and WAITDEFPROCESS - there
2196
* appears to be none, so it is possibly a left-over
2197
* from the 16-bit world. */
2198
break;
2199
}
2200
}
2201
2202
if (!apt->win)
2203
{
2204
/* If window is NULL on apartment, peek at messages so that it will not trigger
2205
* MsgWaitForMultipleObjects next time. */
2206
PeekMessageW(NULL, NULL, 0, 0, PM_QS_POSTMESSAGE | PM_NOREMOVE | PM_NOYIELD);
2207
}
2208
2209
/* Some apps (e.g. Visio 2010) don't handle WM_PAINT properly and loop forever,
2210
* so after processing 100 messages we go back to checking the wait handles */
2211
while (msg_count++ < 100 && com_peek_message(apt, &msg))
2212
{
2213
if (msg.message == WM_QUIT)
2214
{
2215
TRACE("Received WM_QUIT message\n");
2216
quit.post = TRUE;
2217
quit.code = msg.wParam;
2218
}
2219
else
2220
{
2221
TRACE("Received message whilst waiting for RPC: 0x%04x\n", msg.message);
2222
TranslateMessage(&msg);
2223
DispatchMessageW(&msg);
2224
}
2225
}
2226
continue;
2227
}
2228
}
2229
else
2230
{
2231
TRACE("Waiting for rpc completion\n");
2232
2233
res = WaitForMultipleObjectsEx(handle_count, handles, !!(flags & COWAIT_WAITALL),
2234
(timeout == INFINITE) ? INFINITE : start_time + timeout - now, !!(flags & COWAIT_ALERTABLE));
2235
}
2236
2237
switch (res)
2238
{
2239
case WAIT_TIMEOUT:
2240
hr = RPC_S_CALLPENDING;
2241
break;
2242
case WAIT_FAILED:
2243
hr = HRESULT_FROM_WIN32(GetLastError());
2244
break;
2245
default:
2246
*index = res;
2247
break;
2248
}
2249
break;
2250
}
2251
if (quit.post) PostQuitMessage(quit.code);
2252
2253
TRACE("-- %#lx\n", hr);
2254
2255
return hr;
2256
}
2257
2258
/******************************************************************************
2259
* CoRegisterMessageFilter (combase.@)
2260
*/
2261
HRESULT WINAPI CoRegisterMessageFilter(IMessageFilter *filter, IMessageFilter **ret_filter)
2262
{
2263
IMessageFilter *old_filter;
2264
struct apartment *apt;
2265
2266
TRACE("%p, %p\n", filter, ret_filter);
2267
2268
apt = com_get_current_apt();
2269
2270
/* Can't set a message filter in a multi-threaded apartment */
2271
if (!apt || apt->multi_threaded)
2272
{
2273
WARN("Can't set message filter in MTA or uninitialized apt\n");
2274
return CO_E_NOT_SUPPORTED;
2275
}
2276
2277
if (filter)
2278
IMessageFilter_AddRef(filter);
2279
2280
EnterCriticalSection(&apt->cs);
2281
2282
old_filter = apt->filter;
2283
apt->filter = filter;
2284
2285
LeaveCriticalSection(&apt->cs);
2286
2287
if (ret_filter)
2288
*ret_filter = old_filter;
2289
else if (old_filter)
2290
IMessageFilter_Release(old_filter);
2291
2292
return S_OK;
2293
}
2294
2295
static void com_revoke_all_ps_clsids(void)
2296
{
2297
struct registered_ps *cur, *cur2;
2298
2299
EnterCriticalSection(&cs_registered_ps);
2300
2301
LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &registered_proxystubs, struct registered_ps, entry)
2302
{
2303
list_remove(&cur->entry);
2304
free(cur);
2305
}
2306
2307
LeaveCriticalSection(&cs_registered_ps);
2308
}
2309
2310
static HRESULT get_ps_clsid_from_registry(const WCHAR* path, REGSAM access, CLSID *pclsid)
2311
{
2312
WCHAR value[CHARS_IN_GUID];
2313
HKEY hkey;
2314
DWORD len;
2315
2316
access |= KEY_READ;
2317
2318
if (open_classes_key(HKEY_CLASSES_ROOT, path, access, &hkey))
2319
return REGDB_E_IIDNOTREG;
2320
2321
len = sizeof(value);
2322
if (ERROR_SUCCESS != RegQueryValueExW(hkey, NULL, NULL, NULL, (BYTE *)value, &len))
2323
return REGDB_E_IIDNOTREG;
2324
RegCloseKey(hkey);
2325
2326
if (CLSIDFromString(value, pclsid) != NOERROR)
2327
return REGDB_E_IIDNOTREG;
2328
2329
return S_OK;
2330
}
2331
2332
/*****************************************************************************
2333
* CoGetPSClsid (combase.@)
2334
*/
2335
HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
2336
{
2337
static const WCHAR interfaceW[] = L"Interface\\";
2338
static const WCHAR psW[] = L"\\ProxyStubClsid32";
2339
WCHAR path[ARRAY_SIZE(interfaceW) - 1 + CHARS_IN_GUID - 1 + ARRAY_SIZE(psW)];
2340
ACTCTX_SECTION_KEYED_DATA data;
2341
struct registered_ps *cur;
2342
REGSAM opposite = (sizeof(void*) > sizeof(int)) ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
2343
BOOL is_wow64;
2344
HRESULT hr;
2345
2346
TRACE("%s, %p\n", debugstr_guid(riid), pclsid);
2347
2348
if (!InternalIsProcessInitialized())
2349
{
2350
ERR("apartment not initialised\n");
2351
return CO_E_NOTINITIALIZED;
2352
}
2353
2354
if (!pclsid)
2355
return E_INVALIDARG;
2356
2357
EnterCriticalSection(&cs_registered_ps);
2358
2359
LIST_FOR_EACH_ENTRY(cur, &registered_proxystubs, struct registered_ps, entry)
2360
{
2361
if (IsEqualIID(&cur->iid, riid))
2362
{
2363
*pclsid = cur->clsid;
2364
LeaveCriticalSection(&cs_registered_ps);
2365
return S_OK;
2366
}
2367
}
2368
2369
LeaveCriticalSection(&cs_registered_ps);
2370
2371
data.cbSize = sizeof(data);
2372
if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION,
2373
riid, &data))
2374
{
2375
struct ifacepsredirect_data *ifaceps = (struct ifacepsredirect_data *)data.lpData;
2376
*pclsid = ifaceps->iid;
2377
return S_OK;
2378
}
2379
2380
/* Interface\\{string form of riid}\\ProxyStubClsid32 */
2381
lstrcpyW(path, interfaceW);
2382
StringFromGUID2(riid, path + ARRAY_SIZE(interfaceW) - 1, CHARS_IN_GUID);
2383
lstrcpyW(path + ARRAY_SIZE(interfaceW) - 1 + CHARS_IN_GUID - 1, psW);
2384
2385
hr = get_ps_clsid_from_registry(path, KEY_READ, pclsid);
2386
if (FAILED(hr) && (opposite == KEY_WOW64_32KEY || (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
2387
hr = get_ps_clsid_from_registry(path, opposite | KEY_READ, pclsid);
2388
2389
if (hr == S_OK)
2390
TRACE("() Returning CLSID %s\n", debugstr_guid(pclsid));
2391
else
2392
WARN("No PSFactoryBuffer object is registered for IID %s\n", debugstr_guid(riid));
2393
2394
return hr;
2395
}
2396
2397
/*****************************************************************************
2398
* CoRegisterPSClsid (combase.@)
2399
*/
2400
HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid)
2401
{
2402
struct registered_ps *cur;
2403
2404
TRACE("%s, %s\n", debugstr_guid(riid), debugstr_guid(rclsid));
2405
2406
if (!InternalIsProcessInitialized())
2407
{
2408
ERR("apartment not initialised\n");
2409
return CO_E_NOTINITIALIZED;
2410
}
2411
2412
EnterCriticalSection(&cs_registered_ps);
2413
2414
LIST_FOR_EACH_ENTRY(cur, &registered_proxystubs, struct registered_ps, entry)
2415
{
2416
if (IsEqualIID(&cur->iid, riid))
2417
{
2418
cur->clsid = *rclsid;
2419
LeaveCriticalSection(&cs_registered_ps);
2420
return S_OK;
2421
}
2422
}
2423
2424
cur = malloc(sizeof(*cur));
2425
if (!cur)
2426
{
2427
LeaveCriticalSection(&cs_registered_ps);
2428
return E_OUTOFMEMORY;
2429
}
2430
2431
cur->iid = *riid;
2432
cur->clsid = *rclsid;
2433
list_add_head(&registered_proxystubs, &cur->entry);
2434
2435
LeaveCriticalSection(&cs_registered_ps);
2436
2437
return S_OK;
2438
}
2439
2440
struct thread_context
2441
{
2442
IComThreadingInfo IComThreadingInfo_iface;
2443
IContextCallback IContextCallback_iface;
2444
IObjContext IObjContext_iface;
2445
LONG refcount;
2446
};
2447
2448
static inline struct thread_context *impl_from_IComThreadingInfo(IComThreadingInfo *iface)
2449
{
2450
return CONTAINING_RECORD(iface, struct thread_context, IComThreadingInfo_iface);
2451
}
2452
2453
static inline struct thread_context *impl_from_IContextCallback(IContextCallback *iface)
2454
{
2455
return CONTAINING_RECORD(iface, struct thread_context, IContextCallback_iface);
2456
}
2457
2458
static inline struct thread_context *impl_from_IObjContext(IObjContext *iface)
2459
{
2460
return CONTAINING_RECORD(iface, struct thread_context, IObjContext_iface);
2461
}
2462
2463
static HRESULT WINAPI thread_context_info_QueryInterface(IComThreadingInfo *iface, REFIID riid, void **obj)
2464
{
2465
struct thread_context *context = impl_from_IComThreadingInfo(iface);
2466
2467
*obj = NULL;
2468
2469
if (IsEqualIID(riid, &IID_IComThreadingInfo) ||
2470
IsEqualIID(riid, &IID_IUnknown))
2471
{
2472
*obj = &context->IComThreadingInfo_iface;
2473
}
2474
else if (IsEqualIID(riid, &IID_IContextCallback))
2475
{
2476
*obj = &context->IContextCallback_iface;
2477
}
2478
else if (IsEqualIID(riid, &IID_IObjContext))
2479
{
2480
*obj = &context->IObjContext_iface;
2481
}
2482
2483
if (*obj)
2484
{
2485
IUnknown_AddRef((IUnknown *)*obj);
2486
return S_OK;
2487
}
2488
2489
FIXME("interface not implemented %s\n", debugstr_guid(riid));
2490
return E_NOINTERFACE;
2491
}
2492
2493
static ULONG WINAPI thread_context_info_AddRef(IComThreadingInfo *iface)
2494
{
2495
struct thread_context *context = impl_from_IComThreadingInfo(iface);
2496
return InterlockedIncrement(&context->refcount);
2497
}
2498
2499
static ULONG WINAPI thread_context_info_Release(IComThreadingInfo *iface)
2500
{
2501
struct thread_context *context = impl_from_IComThreadingInfo(iface);
2502
2503
/* Context instance is initially created with CoGetContextToken() with refcount set to 0,
2504
releasing context while refcount is at 0 destroys it. */
2505
if (!context->refcount)
2506
{
2507
free(context);
2508
return 0;
2509
}
2510
2511
return InterlockedDecrement(&context->refcount);
2512
}
2513
2514
static HRESULT WINAPI thread_context_info_GetCurrentApartmentType(IComThreadingInfo *iface, APTTYPE *apttype)
2515
{
2516
APTTYPEQUALIFIER qualifier;
2517
2518
TRACE("%p\n", apttype);
2519
2520
return CoGetApartmentType(apttype, &qualifier);
2521
}
2522
2523
static HRESULT WINAPI thread_context_info_GetCurrentThreadType(IComThreadingInfo *iface, THDTYPE *thdtype)
2524
{
2525
APTTYPEQUALIFIER qualifier;
2526
APTTYPE apttype;
2527
HRESULT hr;
2528
2529
hr = CoGetApartmentType(&apttype, &qualifier);
2530
if (FAILED(hr))
2531
return hr;
2532
2533
TRACE("%p\n", thdtype);
2534
2535
switch (apttype)
2536
{
2537
case APTTYPE_STA:
2538
case APTTYPE_MAINSTA:
2539
*thdtype = THDTYPE_PROCESSMESSAGES;
2540
break;
2541
default:
2542
*thdtype = THDTYPE_BLOCKMESSAGES;
2543
break;
2544
}
2545
return S_OK;
2546
}
2547
2548
static HRESULT WINAPI thread_context_info_GetCurrentLogicalThreadId(IComThreadingInfo *iface, GUID *logical_thread_id)
2549
{
2550
TRACE("%p\n", logical_thread_id);
2551
2552
return CoGetCurrentLogicalThreadId(logical_thread_id);
2553
}
2554
2555
static HRESULT WINAPI thread_context_info_SetCurrentLogicalThreadId(IComThreadingInfo *iface, REFGUID logical_thread_id)
2556
{
2557
FIXME("%s stub\n", debugstr_guid(logical_thread_id));
2558
2559
return E_NOTIMPL;
2560
}
2561
2562
static const IComThreadingInfoVtbl thread_context_info_vtbl =
2563
{
2564
thread_context_info_QueryInterface,
2565
thread_context_info_AddRef,
2566
thread_context_info_Release,
2567
thread_context_info_GetCurrentApartmentType,
2568
thread_context_info_GetCurrentThreadType,
2569
thread_context_info_GetCurrentLogicalThreadId,
2570
thread_context_info_SetCurrentLogicalThreadId
2571
};
2572
2573
static HRESULT WINAPI thread_context_callback_QueryInterface(IContextCallback *iface, REFIID riid, void **obj)
2574
{
2575
struct thread_context *context = impl_from_IContextCallback(iface);
2576
return IComThreadingInfo_QueryInterface(&context->IComThreadingInfo_iface, riid, obj);
2577
}
2578
2579
static ULONG WINAPI thread_context_callback_AddRef(IContextCallback *iface)
2580
{
2581
struct thread_context *context = impl_from_IContextCallback(iface);
2582
return IComThreadingInfo_AddRef(&context->IComThreadingInfo_iface);
2583
}
2584
2585
static ULONG WINAPI thread_context_callback_Release(IContextCallback *iface)
2586
{
2587
struct thread_context *context = impl_from_IContextCallback(iface);
2588
return IComThreadingInfo_Release(&context->IComThreadingInfo_iface);
2589
}
2590
2591
static HRESULT WINAPI thread_context_callback_ContextCallback(IContextCallback *iface,
2592
PFNCONTEXTCALL callback, ComCallData *param, REFIID riid, int method, IUnknown *punk)
2593
{
2594
FIXME("%p, %p, %p, %s, %d, %p\n", iface, callback, param, debugstr_guid(riid), method, punk);
2595
2596
return E_NOTIMPL;
2597
}
2598
2599
static const IContextCallbackVtbl thread_context_callback_vtbl =
2600
{
2601
thread_context_callback_QueryInterface,
2602
thread_context_callback_AddRef,
2603
thread_context_callback_Release,
2604
thread_context_callback_ContextCallback
2605
};
2606
2607
static HRESULT WINAPI thread_object_context_QueryInterface(IObjContext *iface, REFIID riid, void **obj)
2608
{
2609
struct thread_context *context = impl_from_IObjContext(iface);
2610
return IComThreadingInfo_QueryInterface(&context->IComThreadingInfo_iface, riid, obj);
2611
}
2612
2613
static ULONG WINAPI thread_object_context_AddRef(IObjContext *iface)
2614
{
2615
struct thread_context *context = impl_from_IObjContext(iface);
2616
return IComThreadingInfo_AddRef(&context->IComThreadingInfo_iface);
2617
}
2618
2619
static ULONG WINAPI thread_object_context_Release(IObjContext *iface)
2620
{
2621
struct thread_context *context = impl_from_IObjContext(iface);
2622
return IComThreadingInfo_Release(&context->IComThreadingInfo_iface);
2623
}
2624
2625
static HRESULT WINAPI thread_object_context_SetProperty(IObjContext *iface, REFGUID propid, CPFLAGS flags, IUnknown *punk)
2626
{
2627
FIXME("%p, %s, %lx, %p\n", iface, debugstr_guid(propid), flags, punk);
2628
2629
return E_NOTIMPL;
2630
}
2631
2632
static HRESULT WINAPI thread_object_context_RemoveProperty(IObjContext *iface, REFGUID propid)
2633
{
2634
FIXME("%p, %s\n", iface, debugstr_guid(propid));
2635
2636
return E_NOTIMPL;
2637
}
2638
2639
static HRESULT WINAPI thread_object_context_GetProperty(IObjContext *iface, REFGUID propid, CPFLAGS *flags, IUnknown **punk)
2640
{
2641
FIXME("%p, %s, %p, %p\n", iface, debugstr_guid(propid), flags, punk);
2642
2643
return E_NOTIMPL;
2644
}
2645
2646
static HRESULT WINAPI thread_object_context_EnumContextProps(IObjContext *iface, IEnumContextProps **props)
2647
{
2648
FIXME("%p, %p\n", iface, props);
2649
2650
return E_NOTIMPL;
2651
}
2652
2653
static void WINAPI thread_object_context_Reserved1(IObjContext *iface)
2654
{
2655
FIXME("%p\n", iface);
2656
}
2657
2658
static void WINAPI thread_object_context_Reserved2(IObjContext *iface)
2659
{
2660
FIXME("%p\n", iface);
2661
}
2662
2663
static void WINAPI thread_object_context_Reserved3(IObjContext *iface)
2664
{
2665
FIXME("%p\n", iface);
2666
}
2667
2668
static void WINAPI thread_object_context_Reserved4(IObjContext *iface)
2669
{
2670
FIXME("%p\n", iface);
2671
}
2672
2673
static void WINAPI thread_object_context_Reserved5(IObjContext *iface)
2674
{
2675
FIXME("%p\n", iface);
2676
}
2677
2678
static void WINAPI thread_object_context_Reserved6(IObjContext *iface)
2679
{
2680
FIXME("%p\n", iface);
2681
}
2682
2683
static void WINAPI thread_object_context_Reserved7(IObjContext *iface)
2684
{
2685
FIXME("%p\n", iface);
2686
}
2687
2688
static const IObjContextVtbl thread_object_context_vtbl =
2689
{
2690
thread_object_context_QueryInterface,
2691
thread_object_context_AddRef,
2692
thread_object_context_Release,
2693
thread_object_context_SetProperty,
2694
thread_object_context_RemoveProperty,
2695
thread_object_context_GetProperty,
2696
thread_object_context_EnumContextProps,
2697
thread_object_context_Reserved1,
2698
thread_object_context_Reserved2,
2699
thread_object_context_Reserved3,
2700
thread_object_context_Reserved4,
2701
thread_object_context_Reserved5,
2702
thread_object_context_Reserved6,
2703
thread_object_context_Reserved7
2704
};
2705
2706
/***********************************************************************
2707
* CoGetContextToken (combase.@)
2708
*/
2709
HRESULT WINAPI CoGetContextToken(ULONG_PTR *token)
2710
{
2711
struct tlsdata *tlsdata;
2712
HRESULT hr;
2713
2714
TRACE("%p\n", token);
2715
2716
if (!InternalIsProcessInitialized())
2717
{
2718
ERR("apartment not initialised\n");
2719
return CO_E_NOTINITIALIZED;
2720
}
2721
2722
if (FAILED(hr = com_get_tlsdata(&tlsdata)))
2723
return hr;
2724
2725
if (!token)
2726
return E_POINTER;
2727
2728
if (!tlsdata->context_token)
2729
{
2730
struct thread_context *context;
2731
2732
context = calloc(1, sizeof(*context));
2733
if (!context)
2734
return E_OUTOFMEMORY;
2735
2736
context->IComThreadingInfo_iface.lpVtbl = &thread_context_info_vtbl;
2737
context->IContextCallback_iface.lpVtbl = &thread_context_callback_vtbl;
2738
context->IObjContext_iface.lpVtbl = &thread_object_context_vtbl;
2739
/* Context token does not take a reference, it's always zero until the
2740
interface is explicitly requested with CoGetObjectContext(). */
2741
context->refcount = 0;
2742
2743
tlsdata->context_token = &context->IObjContext_iface;
2744
}
2745
2746
*token = (ULONG_PTR)tlsdata->context_token;
2747
TRACE("context_token %p\n", tlsdata->context_token);
2748
2749
return S_OK;
2750
}
2751
2752
/***********************************************************************
2753
* CoGetCurrentLogicalThreadId (combase.@)
2754
*/
2755
HRESULT WINAPI CoGetCurrentLogicalThreadId(GUID *id)
2756
{
2757
struct tlsdata *tlsdata;
2758
HRESULT hr;
2759
2760
if (!id)
2761
return E_INVALIDARG;
2762
2763
if (FAILED(hr = com_get_tlsdata(&tlsdata)))
2764
return hr;
2765
2766
if (IsEqualGUID(&tlsdata->causality_id, &GUID_NULL))
2767
{
2768
CoCreateGuid(&tlsdata->causality_id);
2769
tlsdata->flags |= OLETLS_UUIDINITIALIZED;
2770
}
2771
2772
*id = tlsdata->causality_id;
2773
2774
return S_OK;
2775
}
2776
2777
/******************************************************************************
2778
* CoGetCurrentProcess (combase.@)
2779
*/
2780
DWORD WINAPI CoGetCurrentProcess(void)
2781
{
2782
struct tlsdata *tlsdata;
2783
2784
if (FAILED(com_get_tlsdata(&tlsdata)))
2785
return 0;
2786
2787
if (!tlsdata->thread_seqid)
2788
rpcss_get_next_seqid(&tlsdata->thread_seqid);
2789
2790
return tlsdata->thread_seqid;
2791
}
2792
2793
/***********************************************************************
2794
* CoFreeUnusedLibrariesEx (combase.@)
2795
*/
2796
void WINAPI DECLSPEC_HOTPATCH CoFreeUnusedLibrariesEx(DWORD unload_delay, DWORD reserved)
2797
{
2798
struct apartment *apt = com_get_current_apt();
2799
if (!apt)
2800
{
2801
ERR("apartment not initialised\n");
2802
return;
2803
}
2804
2805
apartment_freeunusedlibraries(apt, unload_delay);
2806
}
2807
2808
/*
2809
* When locked, don't modify list (unless we add a new head), so that it's
2810
* safe to iterate it. Freeing of list entries is delayed and done on unlock.
2811
*/
2812
static inline void lock_init_spies(struct tlsdata *tlsdata)
2813
{
2814
tlsdata->spies_lock++;
2815
}
2816
2817
static void unlock_init_spies(struct tlsdata *tlsdata)
2818
{
2819
struct init_spy *spy, *next;
2820
2821
if (--tlsdata->spies_lock) return;
2822
2823
LIST_FOR_EACH_ENTRY_SAFE(spy, next, &tlsdata->spies, struct init_spy, entry)
2824
{
2825
if (spy->spy) continue;
2826
list_remove(&spy->entry);
2827
free(spy);
2828
}
2829
}
2830
2831
/******************************************************************************
2832
* CoInitializeWOW (combase.@)
2833
*/
2834
HRESULT WINAPI CoInitializeWOW(DWORD arg1, DWORD arg2)
2835
{
2836
FIXME("%#lx, %#lx\n", arg1, arg2);
2837
2838
return S_OK;
2839
}
2840
2841
/******************************************************************************
2842
* CoInitializeEx (combase.@)
2843
*/
2844
HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(void *reserved, DWORD model)
2845
{
2846
struct tlsdata *tlsdata;
2847
struct init_spy *cursor;
2848
HRESULT hr;
2849
2850
TRACE("%p, %#lx\n", reserved, model);
2851
2852
if (reserved)
2853
WARN("Unexpected reserved argument %p\n", reserved);
2854
2855
if (FAILED(hr = com_get_tlsdata(&tlsdata)))
2856
return hr;
2857
2858
if (InterlockedExchangeAdd(&com_lockcount, 1) == 0)
2859
TRACE("Initializing the COM libraries\n");
2860
2861
lock_init_spies(tlsdata);
2862
LIST_FOR_EACH_ENTRY(cursor, &tlsdata->spies, struct init_spy, entry)
2863
{
2864
if (cursor->spy) IInitializeSpy_PreInitialize(cursor->spy, model, tlsdata->inits);
2865
}
2866
unlock_init_spies(tlsdata);
2867
2868
hr = enter_apartment(tlsdata, model);
2869
2870
lock_init_spies(tlsdata);
2871
LIST_FOR_EACH_ENTRY(cursor, &tlsdata->spies, struct init_spy, entry)
2872
{
2873
if (cursor->spy) hr = IInitializeSpy_PostInitialize(cursor->spy, hr, model, tlsdata->inits);
2874
}
2875
unlock_init_spies(tlsdata);
2876
2877
return hr;
2878
}
2879
2880
/***********************************************************************
2881
* CoUninitialize (combase.@)
2882
*/
2883
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
2884
{
2885
struct tlsdata *tlsdata;
2886
struct init_spy *cursor, *next;
2887
LONG lockcount;
2888
2889
TRACE("\n");
2890
2891
if (FAILED(com_get_tlsdata(&tlsdata)))
2892
return;
2893
2894
lock_init_spies(tlsdata);
2895
LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &tlsdata->spies, struct init_spy, entry)
2896
{
2897
if (cursor->spy) IInitializeSpy_PreUninitialize(cursor->spy, tlsdata->inits);
2898
}
2899
unlock_init_spies(tlsdata);
2900
2901
/* sanity check */
2902
if (!tlsdata->inits)
2903
{
2904
ERR("Mismatched CoUninitialize\n");
2905
2906
lock_init_spies(tlsdata);
2907
LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &tlsdata->spies, struct init_spy, entry)
2908
{
2909
if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, tlsdata->inits);
2910
}
2911
unlock_init_spies(tlsdata);
2912
2913
return;
2914
}
2915
2916
leave_apartment(tlsdata);
2917
2918
/*
2919
* Decrease the reference count.
2920
* If we are back to 0 locks on the COM library, make sure we free
2921
* all the associated data structures.
2922
*/
2923
lockcount = InterlockedExchangeAdd(&com_lockcount, -1);
2924
if (lockcount == 1)
2925
{
2926
TRACE("Releasing the COM libraries\n");
2927
2928
com_revoke_all_ps_clsids();
2929
DestroyRunningObjectTable();
2930
}
2931
else if (lockcount < 1)
2932
{
2933
ERR("Unbalanced lock count %ld\n", lockcount);
2934
InterlockedExchangeAdd(&com_lockcount, 1);
2935
}
2936
2937
lock_init_spies(tlsdata);
2938
LIST_FOR_EACH_ENTRY(cursor, &tlsdata->spies, struct init_spy, entry)
2939
{
2940
if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, tlsdata->inits);
2941
}
2942
unlock_init_spies(tlsdata);
2943
}
2944
2945
/***********************************************************************
2946
* CoIncrementMTAUsage (combase.@)
2947
*/
2948
HRESULT WINAPI CoIncrementMTAUsage(CO_MTA_USAGE_COOKIE *cookie)
2949
{
2950
TRACE("%p\n", cookie);
2951
2952
return apartment_increment_mta_usage(cookie);
2953
}
2954
2955
/***********************************************************************
2956
* CoDecrementMTAUsage (combase.@)
2957
*/
2958
HRESULT WINAPI CoDecrementMTAUsage(CO_MTA_USAGE_COOKIE cookie)
2959
{
2960
TRACE("%p\n", cookie);
2961
2962
apartment_decrement_mta_usage(cookie);
2963
return S_OK;
2964
}
2965
2966
/***********************************************************************
2967
* CoGetApartmentType (combase.@)
2968
*/
2969
HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier)
2970
{
2971
struct tlsdata *tlsdata;
2972
struct apartment *apt;
2973
HRESULT hr;
2974
2975
TRACE("%p, %p\n", type, qualifier);
2976
2977
if (!type || !qualifier)
2978
return E_INVALIDARG;
2979
2980
if (FAILED(hr = com_get_tlsdata(&tlsdata)))
2981
return hr;
2982
2983
if (!tlsdata->apt)
2984
*type = APTTYPE_CURRENT;
2985
else if (tlsdata->apt->multi_threaded)
2986
*type = APTTYPE_MTA;
2987
else if (tlsdata->apt->main)
2988
*type = APTTYPE_MAINSTA;
2989
else
2990
*type = APTTYPE_STA;
2991
2992
*qualifier = APTTYPEQUALIFIER_NONE;
2993
2994
if (!tlsdata->apt && (apt = apartment_get_mta()))
2995
{
2996
apartment_release(apt);
2997
*type = APTTYPE_MTA;
2998
*qualifier = APTTYPEQUALIFIER_IMPLICIT_MTA;
2999
return S_OK;
3000
}
3001
3002
return tlsdata->apt ? S_OK : CO_E_NOTINITIALIZED;
3003
}
3004
3005
/******************************************************************************
3006
* CoRegisterClassObject (combase.@)
3007
* BUGS
3008
* MSDN claims that multiple interface registrations are legal, but we
3009
* can't do that with our current implementation.
3010
*/
3011
HRESULT WINAPI CoRegisterClassObject(REFCLSID rclsid, IUnknown *object, DWORD clscontext,
3012
DWORD flags, DWORD *cookie)
3013
{
3014
static LONG next_cookie;
3015
3016
struct registered_class *newclass;
3017
IUnknown *found_object;
3018
struct apartment *apt;
3019
HRESULT hr = S_OK;
3020
3021
TRACE("%s, %p, %#lx, %#lx, %p\n", debugstr_guid(rclsid), object, clscontext, flags, cookie);
3022
3023
if (!cookie || !object)
3024
return E_INVALIDARG;
3025
3026
if (!(apt = apartment_get_current_or_mta()))
3027
{
3028
ERR("COM was not initialized\n");
3029
return CO_E_NOTINITIALIZED;
3030
}
3031
3032
*cookie = 0;
3033
3034
/* REGCLS_MULTIPLEUSE implies registering as inproc server. This is what
3035
* differentiates the flag from REGCLS_MULTI_SEPARATE. */
3036
if (flags & REGCLS_MULTIPLEUSE)
3037
clscontext |= CLSCTX_INPROC_SERVER;
3038
3039
/*
3040
* First, check if the class is already registered.
3041
* If it is, this should cause an error.
3042
*/
3043
if ((found_object = com_get_registered_class_object(apt, rclsid, clscontext)))
3044
{
3045
if (flags & REGCLS_MULTIPLEUSE)
3046
{
3047
if (clscontext & CLSCTX_LOCAL_SERVER)
3048
hr = CoLockObjectExternal(found_object, TRUE, FALSE);
3049
IUnknown_Release(found_object);
3050
apartment_release(apt);
3051
return hr;
3052
}
3053
3054
IUnknown_Release(found_object);
3055
ERR("object already registered for class %s\n", debugstr_guid(rclsid));
3056
apartment_release(apt);
3057
return CO_E_OBJISREG;
3058
}
3059
3060
newclass = calloc(1, sizeof(*newclass));
3061
if (!newclass)
3062
{
3063
apartment_release(apt);
3064
return E_OUTOFMEMORY;
3065
}
3066
3067
newclass->clsid = *rclsid;
3068
newclass->apartment_id = apt->oxid;
3069
newclass->clscontext = clscontext;
3070
newclass->flags = flags;
3071
3072
if (!(newclass->cookie = InterlockedIncrement(&next_cookie)))
3073
newclass->cookie = InterlockedIncrement(&next_cookie);
3074
3075
newclass->object = object;
3076
IUnknown_AddRef(newclass->object);
3077
3078
EnterCriticalSection(&registered_classes_cs);
3079
list_add_tail(&registered_classes, &newclass->entry);
3080
LeaveCriticalSection(&registered_classes_cs);
3081
3082
*cookie = newclass->cookie;
3083
3084
if (clscontext & CLSCTX_LOCAL_SERVER)
3085
{
3086
IStream *marshal_stream;
3087
3088
hr = apartment_get_local_server_stream(apt, &marshal_stream);
3089
if(FAILED(hr))
3090
{
3091
apartment_release(apt);
3092
return hr;
3093
}
3094
3095
hr = rpc_register_local_server(&newclass->clsid, marshal_stream, flags, &newclass->rpcss_cookie);
3096
IStream_Release(marshal_stream);
3097
}
3098
3099
apartment_release(apt);
3100
return S_OK;
3101
}
3102
3103
static void com_revoke_class_object(struct registered_class *entry)
3104
{
3105
list_remove(&entry->entry);
3106
3107
if (entry->clscontext & CLSCTX_LOCAL_SERVER)
3108
rpc_revoke_local_server(entry->rpcss_cookie);
3109
3110
IUnknown_Release(entry->object);
3111
free(entry);
3112
}
3113
3114
/* Cleans up rpcss registry */
3115
static void com_revoke_local_servers(void)
3116
{
3117
struct registered_class *cur, *cur2;
3118
3119
EnterCriticalSection(&registered_classes_cs);
3120
3121
LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &registered_classes, struct registered_class, entry)
3122
{
3123
if (cur->clscontext & CLSCTX_LOCAL_SERVER)
3124
com_revoke_class_object(cur);
3125
}
3126
3127
LeaveCriticalSection(&registered_classes_cs);
3128
}
3129
3130
void apartment_revoke_all_classes(const struct apartment *apt)
3131
{
3132
struct registered_class *cur, *cur2;
3133
3134
EnterCriticalSection(&registered_classes_cs);
3135
3136
LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &registered_classes, struct registered_class, entry)
3137
{
3138
if (cur->apartment_id == apt->oxid)
3139
com_revoke_class_object(cur);
3140
}
3141
3142
LeaveCriticalSection(&registered_classes_cs);
3143
}
3144
3145
/***********************************************************************
3146
* CoRevokeClassObject (combase.@)
3147
*/
3148
HRESULT WINAPI DECLSPEC_HOTPATCH CoRevokeClassObject(DWORD cookie)
3149
{
3150
HRESULT hr = E_INVALIDARG;
3151
struct registered_class *cur;
3152
struct apartment *apt;
3153
3154
TRACE("%#lx\n", cookie);
3155
3156
if (!(apt = apartment_get_current_or_mta()))
3157
{
3158
ERR("COM was not initialized\n");
3159
return CO_E_NOTINITIALIZED;
3160
}
3161
3162
EnterCriticalSection(&registered_classes_cs);
3163
3164
LIST_FOR_EACH_ENTRY(cur, &registered_classes, struct registered_class, entry)
3165
{
3166
if (cur->cookie != cookie)
3167
continue;
3168
3169
if (cur->apartment_id == apt->oxid)
3170
{
3171
com_revoke_class_object(cur);
3172
hr = S_OK;
3173
}
3174
else
3175
{
3176
ERR("called from wrong apartment, should be called from %s\n", wine_dbgstr_longlong(cur->apartment_id));
3177
hr = RPC_E_WRONG_THREAD;
3178
}
3179
3180
break;
3181
}
3182
3183
LeaveCriticalSection(&registered_classes_cs);
3184
apartment_release(apt);
3185
3186
return hr;
3187
}
3188
3189
/***********************************************************************
3190
* CoAddRefServerProcess (combase.@)
3191
*/
3192
ULONG WINAPI CoAddRefServerProcess(void)
3193
{
3194
ULONG refs;
3195
3196
TRACE("\n");
3197
3198
EnterCriticalSection(&registered_classes_cs);
3199
refs = ++com_server_process_refcount;
3200
LeaveCriticalSection(&registered_classes_cs);
3201
3202
TRACE("refs before: %ld\n", refs - 1);
3203
3204
return refs;
3205
}
3206
3207
/***********************************************************************
3208
* CoReleaseServerProcess [OLE32.@]
3209
*/
3210
ULONG WINAPI CoReleaseServerProcess(void)
3211
{
3212
ULONG refs;
3213
3214
TRACE("\n");
3215
3216
EnterCriticalSection(&registered_classes_cs);
3217
3218
refs = --com_server_process_refcount;
3219
/* FIXME: suspend objects */
3220
3221
LeaveCriticalSection(&registered_classes_cs);
3222
3223
TRACE("refs after: %ld\n", refs);
3224
3225
return refs;
3226
}
3227
3228
/******************************************************************************
3229
* CoDisconnectObject (combase.@)
3230
*/
3231
HRESULT WINAPI CoDisconnectObject(IUnknown *object, DWORD reserved)
3232
{
3233
struct stub_manager *manager;
3234
struct apartment *apt;
3235
IMarshal *marshal;
3236
HRESULT hr;
3237
3238
TRACE("%p, %#lx\n", object, reserved);
3239
3240
if (!object)
3241
return E_INVALIDARG;
3242
3243
hr = IUnknown_QueryInterface(object, &IID_IMarshal, (void **)&marshal);
3244
if (hr == S_OK)
3245
{
3246
hr = IMarshal_DisconnectObject(marshal, reserved);
3247
IMarshal_Release(marshal);
3248
return hr;
3249
}
3250
3251
if (!(apt = apartment_get_current_or_mta()))
3252
{
3253
ERR("apartment not initialised\n");
3254
return CO_E_NOTINITIALIZED;
3255
}
3256
3257
manager = get_stub_manager_from_object(apt, object, FALSE);
3258
if (manager)
3259
{
3260
stub_manager_disconnect(manager);
3261
/* Release stub manager twice, to remove the apartment reference. */
3262
stub_manager_int_release(manager);
3263
stub_manager_int_release(manager);
3264
}
3265
3266
/* Note: native is pretty broken here because it just silently
3267
* fails, without returning an appropriate error code if the object was
3268
* not found, making apps think that the object was disconnected, when
3269
* it actually wasn't */
3270
3271
apartment_release(apt);
3272
return S_OK;
3273
}
3274
3275
/******************************************************************************
3276
* CoLockObjectExternal (combase.@)
3277
*/
3278
HRESULT WINAPI CoLockObjectExternal(IUnknown *object, BOOL lock, BOOL last_unlock_releases)
3279
{
3280
struct stub_manager *stubmgr;
3281
struct apartment *apt;
3282
3283
TRACE("%p, %d, %d\n", object, lock, last_unlock_releases);
3284
3285
if (!(apt = apartment_get_current_or_mta()))
3286
{
3287
ERR("apartment not initialised\n");
3288
return CO_E_NOTINITIALIZED;
3289
}
3290
3291
stubmgr = get_stub_manager_from_object(apt, object, lock);
3292
if (!stubmgr)
3293
{
3294
WARN("stub object not found %p\n", object);
3295
/* Note: native is pretty broken here because it just silently
3296
* fails, without returning an appropriate error code, making apps
3297
* think that the object was disconnected, when it actually wasn't */
3298
apartment_release(apt);
3299
return S_OK;
3300
}
3301
3302
if (lock)
3303
stub_manager_ext_addref(stubmgr, 1, FALSE);
3304
else
3305
stub_manager_ext_release(stubmgr, 1, FALSE, last_unlock_releases);
3306
3307
stub_manager_int_release(stubmgr);
3308
apartment_release(apt);
3309
return S_OK;
3310
}
3311
3312
/***********************************************************************
3313
* CoRegisterChannelHook (combase.@)
3314
*/
3315
HRESULT WINAPI CoRegisterChannelHook(REFGUID guidExtension, IChannelHook *channel_hook)
3316
{
3317
TRACE("%s, %p\n", debugstr_guid(guidExtension), channel_hook);
3318
3319
return rpc_register_channel_hook(guidExtension, channel_hook);
3320
}
3321
3322
/***********************************************************************
3323
* CoDisableCallCancellation (combase.@)
3324
*/
3325
HRESULT WINAPI CoDisableCallCancellation(void *reserved)
3326
{
3327
struct tlsdata *tlsdata;
3328
HRESULT hr;
3329
3330
TRACE("%p\n", reserved);
3331
3332
if (FAILED(hr = com_get_tlsdata(&tlsdata)))
3333
return hr;
3334
3335
if (!tlsdata->cancelcount)
3336
return CO_E_CANCEL_DISABLED;
3337
3338
tlsdata->cancelcount--;
3339
3340
return S_OK;
3341
}
3342
3343
/***********************************************************************
3344
* CoEnableCallCancellation (combase.@)
3345
*/
3346
HRESULT WINAPI CoEnableCallCancellation(void *reserved)
3347
{
3348
struct tlsdata *tlsdata;
3349
HRESULT hr;
3350
3351
TRACE("%p\n", reserved);
3352
3353
if (FAILED(hr = com_get_tlsdata(&tlsdata)))
3354
return hr;
3355
3356
tlsdata->cancelcount++;
3357
3358
return S_OK;
3359
}
3360
3361
/***********************************************************************
3362
* CoGetCallerTID (combase.@)
3363
*/
3364
HRESULT WINAPI CoGetCallerTID(DWORD *tid)
3365
{
3366
FIXME("stub!\n");
3367
return E_NOTIMPL;
3368
}
3369
3370
/***********************************************************************
3371
* CoIsHandlerConnected (combase.@)
3372
*/
3373
BOOL WINAPI CoIsHandlerConnected(IUnknown *object)
3374
{
3375
FIXME("%p\n", object);
3376
3377
return TRUE;
3378
}
3379
3380
/***********************************************************************
3381
* CoSuspendClassObjects (combase.@)
3382
*/
3383
HRESULT WINAPI CoSuspendClassObjects(void)
3384
{
3385
FIXME("\n");
3386
3387
return S_OK;
3388
}
3389
3390
/***********************************************************************
3391
* CoResumeClassObjects (combase.@)
3392
*/
3393
HRESULT WINAPI CoResumeClassObjects(void)
3394
{
3395
FIXME("stub\n");
3396
3397
return S_OK;
3398
}
3399
3400
/***********************************************************************
3401
* CoRegisterSurrogate (combase.@)
3402
*/
3403
HRESULT WINAPI CoRegisterSurrogate(ISurrogate *surrogate)
3404
{
3405
FIXME("%p stub\n", surrogate);
3406
3407
return E_NOTIMPL;
3408
}
3409
3410
/***********************************************************************
3411
* CoRegisterSurrogateEx (combase.@)
3412
*/
3413
HRESULT WINAPI CoRegisterSurrogateEx(REFGUID guid, void *reserved)
3414
{
3415
FIXME("%s, %p stub\n", debugstr_guid(guid), reserved);
3416
3417
return E_NOTIMPL;
3418
}
3419
3420
/***********************************************************************
3421
* CoIsOle1Class (combase.@)
3422
*/
3423
BOOL WINAPI CoIsOle1Class(REFCLSID clsid)
3424
{
3425
FIXME("%s\n", debugstr_guid(clsid));
3426
return FALSE;
3427
}
3428
3429
/***********************************************************************
3430
* DllMain (combase.@)
3431
*/
3432
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
3433
{
3434
TRACE("%p, %#lx, %p\n", hinstDLL, reason, reserved);
3435
3436
switch (reason)
3437
{
3438
case DLL_PROCESS_ATTACH:
3439
hProxyDll = hinstDLL;
3440
break;
3441
case DLL_PROCESS_DETACH:
3442
com_revoke_local_servers();
3443
if (reserved) break;
3444
apartment_global_cleanup();
3445
DeleteCriticalSection(&registered_classes_cs);
3446
rpc_unregister_channel_hooks();
3447
break;
3448
case DLL_THREAD_DETACH:
3449
com_cleanup_tlsdata();
3450
break;
3451
}
3452
3453
return TRUE;
3454
}
3455
3456
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **obj)
3457
{
3458
TRACE("%s, %s, %p.\n", debugstr_guid(rclsid), debugstr_guid(riid), obj);
3459
3460
*obj = NULL;
3461
3462
if (IsEqualCLSID(rclsid, &CLSID_GlobalOptions))
3463
return IClassFactory_QueryInterface(&global_options_factory, riid, obj);
3464
3465
return CLASS_E_CLASSNOTAVAILABLE;
3466
}
3467
3468