Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/combase/tests/roapi.c
4394 views
1
/*
2
* Copyright (c) 2018 Alistair Leslie-Hughes
3
*
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
8
*
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
13
*
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17
*/
18
#define COBJMACROS
19
#include <stdarg.h>
20
21
#include "windef.h"
22
#include "winbase.h"
23
#include "winerror.h"
24
#include "winstring.h"
25
#include "winternl.h"
26
27
#include "initguid.h"
28
#include "roapi.h"
29
#include "roerrorapi.h"
30
31
#include "wine/test.h"
32
33
#define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
34
static void _expect_ref(IUnknown* obj, ULONG ref, int line)
35
{
36
ULONG rc;
37
IUnknown_AddRef(obj);
38
rc = IUnknown_Release(obj);
39
ok_(__FILE__,line)(rc == ref, "expected refcount %ld, got %ld\n", ref, rc);
40
}
41
42
static void flush_events(void)
43
{
44
int diff = 200;
45
DWORD time;
46
MSG msg;
47
48
time = GetTickCount() + diff;
49
while (diff > 0)
50
{
51
if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
52
break;
53
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
54
DispatchMessageA(&msg);
55
diff = time - GetTickCount();
56
}
57
}
58
59
static void load_resource(const WCHAR *filename)
60
{
61
DWORD written;
62
HANDLE file;
63
HRSRC res;
64
void *ptr;
65
66
file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
67
ok(file != INVALID_HANDLE_VALUE, "failed to create %s, error %lu\n", debugstr_w(filename), GetLastError());
68
69
res = FindResourceW(NULL, filename, L"TESTDLL");
70
ok(res != 0, "couldn't find resource\n");
71
ptr = LockResource(LoadResource(GetModuleHandleW(NULL), res));
72
WriteFile(file, ptr, SizeofResource(GetModuleHandleW(NULL), res), &written, NULL);
73
ok(written == SizeofResource(GetModuleHandleW(NULL), res), "couldn't write resource\n");
74
CloseHandle(file);
75
}
76
77
static void test_ActivationFactories(void)
78
{
79
HRESULT hr;
80
HSTRING str, str2;
81
IActivationFactory *factory = NULL;
82
IInspectable *inspect = NULL;
83
ULONG ref;
84
85
hr = WindowsCreateString(L"Windows.Data.Xml.Dom.XmlDocument",
86
ARRAY_SIZE(L"Windows.Data.Xml.Dom.XmlDocument") - 1, &str);
87
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
88
89
hr = WindowsCreateString(L"Does.Not.Exist", ARRAY_SIZE(L"Does.Not.Exist") - 1, &str2);
90
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
91
92
hr = RoInitialize(RO_INIT_MULTITHREADED);
93
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
94
95
hr = RoGetActivationFactory(str2, &IID_IActivationFactory, (void **)&factory);
96
ok(hr == REGDB_E_CLASSNOTREG, "Unexpected hr %#lx.\n", hr);
97
98
hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
99
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
100
if(factory)
101
IActivationFactory_Release(factory);
102
103
hr = RoActivateInstance(str2, &inspect);
104
ok(hr == REGDB_E_CLASSNOTREG, "Unexpected hr %#lx.\n", hr);
105
106
hr = RoActivateInstance(str, &inspect);
107
todo_wine ok(hr == S_OK, "UNexpected hr %#lx.\n", hr);
108
if(inspect)
109
IInspectable_Release(inspect);
110
111
WindowsDeleteString(str2);
112
WindowsDeleteString(str);
113
114
hr = WindowsCreateString(L"Wine.Test.Missing", ARRAY_SIZE(L"Wine.Test.Missing") - 1, &str);
115
ok(hr == S_OK, "WindowsCreateString returned %#lx.\n", hr);
116
hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
117
ok(hr == REGDB_E_CLASSNOTREG, "RoGetActivationFactory returned %#lx.\n", hr);
118
ok(factory == NULL, "got factory %p.\n", factory);
119
WindowsDeleteString(str);
120
hr = WindowsCreateString(L"Wine.Test.Class", ARRAY_SIZE(L"Wine.Test.Class") - 1, &str);
121
ok(hr == S_OK, "WindowsCreateString returned %#lx.\n", hr);
122
hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
123
todo_wine
124
ok(hr == E_NOTIMPL || broken(hr == REGDB_E_CLASSNOTREG) /* <= w1064v1809 */,
125
"RoGetActivationFactory returned %#lx.\n", hr);
126
todo_wine
127
ok(factory == NULL, "got factory %p.\n", factory);
128
if (factory) IActivationFactory_Release(factory);
129
WindowsDeleteString(str);
130
hr = WindowsCreateString(L"Wine.Test.Trusted", ARRAY_SIZE(L"Wine.Test.Trusted") - 1, &str);
131
ok(hr == S_OK, "WindowsCreateString returned %#lx.\n", hr);
132
hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
133
ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG) /* <= w1064v1809 */,
134
"RoGetActivationFactory returned %#lx.\n", hr);
135
if (hr == REGDB_E_CLASSNOTREG)
136
ok(!factory, "got factory %p.\n", factory);
137
else
138
ok(!!factory, "got factory %p.\n", factory);
139
if (!factory) ref = 0;
140
else ref = IActivationFactory_Release(factory);
141
ok(ref == 0, "Release returned %lu\n", ref);
142
WindowsDeleteString(str);
143
144
RoUninitialize();
145
}
146
147
static APTTYPE check_thread_apttype;
148
static APTTYPEQUALIFIER check_thread_aptqualifier;
149
static HRESULT check_thread_hr;
150
151
static DWORD WINAPI check_apartment_thread(void *dummy)
152
{
153
check_thread_apttype = 0xdeadbeef;
154
check_thread_aptqualifier = 0xdeadbeef;
155
check_thread_hr = CoGetApartmentType(&check_thread_apttype, &check_thread_aptqualifier);
156
return 0;
157
}
158
159
#define check_thread_apartment(a) check_thread_apartment_(__LINE__, FALSE, a)
160
#define check_thread_apartment_broken(a) check_thread_apartment_(__LINE__, TRUE, a)
161
static void check_thread_apartment_(unsigned int line, BOOL broken_fail, HRESULT expected_hr_thread)
162
{
163
HANDLE thread;
164
165
check_thread_hr = 0xdeadbeef;
166
thread = CreateThread(NULL, 0, check_apartment_thread, NULL, 0, NULL);
167
WaitForSingleObject(thread, INFINITE);
168
CloseHandle(thread);
169
ok_(__FILE__, line)(check_thread_hr == expected_hr_thread
170
|| broken(broken_fail && expected_hr_thread == S_OK && check_thread_hr == CO_E_NOTINITIALIZED),
171
"got %#lx, expected %#lx.\n", check_thread_hr, expected_hr_thread);
172
if (SUCCEEDED(check_thread_hr))
173
{
174
ok_(__FILE__, line)(check_thread_apttype == APTTYPE_MTA, "got %d.\n", check_thread_apttype);
175
ok_(__FILE__, line)(check_thread_aptqualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "got %d.\n", check_thread_aptqualifier);
176
}
177
}
178
179
static HANDLE mta_init_thread_init_done_event, mta_init_thread_done_event;
180
181
static DWORD WINAPI mta_init_thread(void *dummy)
182
{
183
HRESULT hr;
184
185
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
186
ok(hr == S_OK, "got %#lx.\n", hr);
187
SetEvent(mta_init_thread_init_done_event);
188
189
WaitForSingleObject(mta_init_thread_done_event, INFINITE);
190
CoUninitialize();
191
return 0;
192
}
193
194
static DWORD WINAPI mta_init_implicit_thread(void *dummy)
195
{
196
IActivationFactory *factory;
197
HSTRING str;
198
HRESULT hr;
199
200
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
201
ok(hr == S_OK, "got %#lx.\n", hr);
202
203
hr = WindowsCreateString(L"Does.Not.Exist", ARRAY_SIZE(L"Does.Not.Exist") - 1, &str);
204
ok(hr == S_OK, "got %#lx.\n", hr);
205
hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
206
ok(hr == REGDB_E_CLASSNOTREG, "got %#lx.\n", hr);
207
WindowsDeleteString(str);
208
209
SetEvent(mta_init_thread_init_done_event);
210
WaitForSingleObject(mta_init_thread_done_event, INFINITE);
211
212
/* No CoUninitialize(), testing cleanup on thread exit. */
213
return 0;
214
}
215
216
enum oletlsflags
217
{
218
OLETLS_UUIDINITIALIZED = 0x2,
219
OLETLS_DISABLE_OLE1DDE = 0x40,
220
OLETLS_APARTMENTTHREADED = 0x80,
221
OLETLS_MULTITHREADED = 0x100,
222
};
223
224
struct oletlsdata
225
{
226
void *threadbase;
227
void *smallocator;
228
DWORD id;
229
DWORD flags;
230
};
231
232
static DWORD get_oletlsflags(void)
233
{
234
struct oletlsdata *data = NtCurrentTeb()->ReservedForOle;
235
return data ? data->flags : 0;
236
}
237
238
static void test_implicit_mta(void)
239
{
240
static const struct
241
{
242
BOOL ro_init;
243
BOOL mta;
244
}
245
tests[] =
246
{
247
{ FALSE, FALSE },
248
{ FALSE, TRUE },
249
{ TRUE, FALSE },
250
{ TRUE, TRUE },
251
};
252
APTTYPEQUALIFIER aptqualifier;
253
IActivationFactory *factory;
254
APTTYPE apttype;
255
unsigned int i;
256
HANDLE thread;
257
HSTRING str;
258
HRESULT hr;
259
260
hr = WindowsCreateString(L"Does.Not.Exist", ARRAY_SIZE(L"Does.Not.Exist") - 1, &str);
261
ok(hr == S_OK, "got %#lx.\n", hr);
262
/* RoGetActivationFactory doesn't implicitly initialize COM. */
263
hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
264
ok(hr == CO_E_NOTINITIALIZED, "got %#lx.\n", hr);
265
266
check_thread_apartment(CO_E_NOTINITIALIZED);
267
268
/* RoGetActivationFactory initializes implicit MTA. */
269
for (i = 0; i < ARRAY_SIZE(tests); ++i)
270
{
271
winetest_push_context("test %u", i);
272
if (tests[i].ro_init)
273
{
274
DWORD flags = tests[i].mta ? OLETLS_MULTITHREADED : OLETLS_APARTMENTTHREADED;
275
276
hr = RoInitialize(tests[i].mta ? RO_INIT_MULTITHREADED : RO_INIT_SINGLETHREADED);
277
278
flags |= OLETLS_DISABLE_OLE1DDE;
279
ok((get_oletlsflags() & flags) == flags, "get_oletlsflags() = %lx\n", get_oletlsflags());
280
}
281
else
282
hr = CoInitializeEx(NULL, tests[i].mta ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED);
283
ok(hr == S_OK, "got %#lx.\n", hr);
284
check_thread_apartment(tests[i].mta ? S_OK : CO_E_NOTINITIALIZED);
285
hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
286
ok(hr == REGDB_E_CLASSNOTREG, "got %#lx.\n", hr);
287
check_thread_apartment_broken(S_OK); /* Broken on Win8. */
288
hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
289
ok(hr == REGDB_E_CLASSNOTREG, "got %#lx.\n", hr);
290
check_thread_apartment_broken(S_OK); /* Broken on Win8. */
291
if (tests[i].ro_init)
292
RoUninitialize();
293
else
294
CoUninitialize();
295
check_thread_apartment(CO_E_NOTINITIALIZED);
296
winetest_pop_context();
297
}
298
299
mta_init_thread_init_done_event = CreateEventW(NULL, FALSE, FALSE, NULL);
300
mta_init_thread_done_event = CreateEventW(NULL, FALSE, FALSE, NULL);
301
302
/* RoGetActivationFactory references implicit MTA in a current thread
303
* even if implicit MTA was already initialized: check with STA init
304
* after RoGetActivationFactory(). */
305
thread = CreateThread(NULL, 0, mta_init_thread, NULL, 0, NULL);
306
ok(!!thread, "failed.\n");
307
WaitForSingleObject(mta_init_thread_init_done_event, INFINITE);
308
check_thread_apartment(S_OK);
309
310
hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
311
ok(hr == REGDB_E_CLASSNOTREG, "got %#lx.\n", hr);
312
check_thread_apartment(S_OK);
313
314
hr = CoGetApartmentType(&apttype, &aptqualifier);
315
ok(hr == S_OK, "got %#lx.\n", hr);
316
ok(apttype == APTTYPE_MTA, "got %d.\n", apttype);
317
ok(aptqualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "got %d.\n", aptqualifier);
318
319
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
320
ok(hr == S_OK, "got %#lx.\n", hr);
321
322
hr = CoGetApartmentType(&apttype, &aptqualifier);
323
ok(hr == S_OK, "got %#lx.\n", hr);
324
ok(apttype == APTTYPE_MAINSTA, "got %d.\n", apttype);
325
ok(aptqualifier == APTTYPEQUALIFIER_NONE, "got %d.\n", aptqualifier);
326
327
SetEvent(mta_init_thread_done_event);
328
WaitForSingleObject(thread, INFINITE);
329
CloseHandle(thread);
330
check_thread_apartment_broken(S_OK); /* Broken on Win8. */
331
CoUninitialize();
332
check_thread_apartment(CO_E_NOTINITIALIZED);
333
334
/* RoGetActivationFactory references implicit MTA in a current thread
335
* even if implicit MTA was already initialized: check with STA init
336
* before RoGetActivationFactory(). */
337
thread = CreateThread(NULL, 0, mta_init_thread, NULL, 0, NULL);
338
ok(!!thread, "failed.\n");
339
WaitForSingleObject(mta_init_thread_init_done_event, INFINITE);
340
check_thread_apartment(S_OK);
341
342
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
343
ok(hr == S_OK, "got %#lx.\n", hr);
344
345
hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
346
ok(hr == REGDB_E_CLASSNOTREG, "got %#lx.\n", hr);
347
check_thread_apartment(S_OK);
348
349
SetEvent(mta_init_thread_done_event);
350
WaitForSingleObject(thread, INFINITE);
351
CloseHandle(thread);
352
check_thread_apartment_broken(S_OK); /* Broken on Win8. */
353
CoUninitialize();
354
check_thread_apartment(CO_E_NOTINITIALIZED);
355
356
/* Test implicit MTA apartment thread exit. */
357
thread = CreateThread(NULL, 0, mta_init_implicit_thread, NULL, 0, NULL);
358
ok(!!thread, "failed.\n");
359
WaitForSingleObject(mta_init_thread_init_done_event, INFINITE);
360
check_thread_apartment_broken(S_OK); /* Broken on Win8. */
361
SetEvent(mta_init_thread_done_event);
362
WaitForSingleObject(thread, INFINITE);
363
CloseHandle(thread);
364
check_thread_apartment(CO_E_NOTINITIALIZED);
365
366
CloseHandle(mta_init_thread_init_done_event);
367
CloseHandle(mta_init_thread_done_event);
368
WindowsDeleteString(str);
369
}
370
371
struct unk_impl
372
{
373
IUnknown IUnknown_iface;
374
LONG ref;
375
};
376
377
static inline struct unk_impl *impl_from_IUnknown(IUnknown *iface)
378
{
379
return CONTAINING_RECORD(iface, struct unk_impl, IUnknown_iface);
380
}
381
382
static HRESULT WINAPI unk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
383
{
384
if (IsEqualGUID(riid, &IID_IUnknown))
385
{
386
*ppv = iface;
387
IUnknown_AddRef(iface);
388
return S_OK;
389
}
390
391
return E_NOINTERFACE;
392
}
393
394
static HRESULT WINAPI unk_no_marshal_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
395
{
396
if (IsEqualGUID(riid, &IID_IUnknown)
397
|| IsEqualGUID(riid, &IID_INoMarshal))
398
{
399
*ppv = iface;
400
IUnknown_AddRef(iface);
401
return S_OK;
402
}
403
404
return E_NOINTERFACE;
405
}
406
407
static HRESULT WINAPI unk_agile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
408
{
409
if (IsEqualGUID(riid, &IID_IUnknown)
410
|| IsEqualGUID(riid, &IID_IAgileObject))
411
{
412
*ppv = iface;
413
IUnknown_AddRef(iface);
414
return S_OK;
415
}
416
417
return E_NOINTERFACE;
418
}
419
420
static ULONG WINAPI unk_AddRef(IUnknown *iface)
421
{
422
struct unk_impl *impl = impl_from_IUnknown(iface);
423
return InterlockedIncrement(&impl->ref);
424
}
425
426
static ULONG WINAPI unk_Release(IUnknown *iface)
427
{
428
struct unk_impl *impl = impl_from_IUnknown(iface);
429
return InterlockedDecrement(&impl->ref);
430
}
431
432
static const IUnknownVtbl unk_vtbl =
433
{
434
unk_QueryInterface,
435
unk_AddRef,
436
unk_Release
437
};
438
439
static const IUnknownVtbl unk_no_marshal_vtbl =
440
{
441
unk_no_marshal_QueryInterface,
442
unk_AddRef,
443
unk_Release
444
};
445
446
static const IUnknownVtbl unk_agile_vtbl =
447
{
448
unk_agile_QueryInterface,
449
unk_AddRef,
450
unk_Release
451
};
452
453
struct test_RoGetAgileReference_thread_param
454
{
455
enum AgileReferenceOptions option;
456
RO_INIT_TYPE from_type;
457
RO_INIT_TYPE to_type;
458
IAgileReference *agile_reference;
459
IUnknown *unk_obj;
460
BOOLEAN obj_is_agile;
461
};
462
463
static DWORD CALLBACK test_RoGetAgileReference_thread_proc(void *arg)
464
{
465
struct test_RoGetAgileReference_thread_param *param = (struct test_RoGetAgileReference_thread_param *)arg;
466
IUnknown *unknown;
467
HRESULT hr;
468
469
winetest_push_context("%d %d %d", param->option, param->from_type, param->to_type);
470
471
RoInitialize(param->to_type);
472
473
unknown = NULL;
474
hr = IAgileReference_Resolve(param->agile_reference, &IID_IUnknown, (void **)&unknown);
475
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
476
ok(!!unknown, "Expected pointer not NULL.\n");
477
if (param->obj_is_agile)
478
{
479
ok(unknown == param->unk_obj, "Expected the same object.\n");
480
EXPECT_REF(param->unk_obj, 4);
481
}
482
else if (param->from_type == RO_INIT_MULTITHREADED && param->to_type == RO_INIT_MULTITHREADED)
483
{
484
ok(unknown == param->unk_obj, "Expected the same object.\n");
485
todo_wine_if(param->option == AGILEREFERENCE_DEFAULT)
486
EXPECT_REF(param->unk_obj, param->option == AGILEREFERENCE_DEFAULT ? 5 : 6);
487
}
488
else
489
{
490
ok(unknown != param->unk_obj, "Expected a different object pointer.\n");
491
todo_wine_if(param->option == AGILEREFERENCE_DEFAULT)
492
EXPECT_REF(param->unk_obj, param->option == AGILEREFERENCE_DEFAULT ? 4 : 5);
493
EXPECT_REF(unknown, 1);
494
}
495
IUnknown_Release(unknown);
496
497
RoUninitialize();
498
winetest_pop_context();
499
return 0;
500
}
501
502
static void test_RoGetAgileReference(void)
503
{
504
struct test_RoGetAgileReference_thread_param param;
505
struct unk_impl unk_no_marshal_obj = {{&unk_no_marshal_vtbl}, 1};
506
struct unk_impl unk_obj = {{&unk_vtbl}, 1};
507
struct unk_impl unk_agile_obj = {{&unk_agile_vtbl}, 1};
508
enum AgileReferenceOptions option;
509
IAgileReference *agile_reference;
510
RO_INIT_TYPE from_type, to_type;
511
IUnknown *unknown, *unknown2;
512
IAgileObject *agile_object;
513
HANDLE thread;
514
HRESULT hr;
515
DWORD ret;
516
517
for (option = AGILEREFERENCE_DEFAULT; option <= AGILEREFERENCE_DELAYEDMARSHAL; option++)
518
{
519
for (from_type = RO_INIT_SINGLETHREADED; from_type <= RO_INIT_MULTITHREADED; from_type++)
520
{
521
winetest_push_context("%d %d", option, from_type);
522
523
hr = RoGetAgileReference(option, &IID_IUnknown, &unk_obj.IUnknown_iface, &agile_reference);
524
ok(hr == CO_E_NOTINITIALIZED, "Got unexpected hr %#lx.\n", hr);
525
526
RoInitialize(from_type);
527
528
agile_reference = NULL;
529
EXPECT_REF(&unk_obj, 1);
530
531
/* Invalid option */
532
hr = RoGetAgileReference(AGILEREFERENCE_DELAYEDMARSHAL + 1, &IID_IUnknown, &unk_obj.IUnknown_iface, &agile_reference);
533
ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
534
535
/* Non-existent interface for the object */
536
hr = RoGetAgileReference(option, &IID_IActivationFactory, &unk_obj.IUnknown_iface, &agile_reference);
537
ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr);
538
539
/* Objects that implements INoMarshal */
540
hr = RoGetAgileReference(option, &IID_IUnknown, &unk_no_marshal_obj.IUnknown_iface, &agile_reference);
541
ok(hr == CO_E_NOT_SUPPORTED, "Got unexpected hr %#lx.\n", hr);
542
543
/* Create agile reference object */
544
hr = RoGetAgileReference(option, &IID_IUnknown, &unk_obj.IUnknown_iface, &agile_reference);
545
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
546
ok(!!agile_reference, "Got unexpected agile_reference.\n");
547
todo_wine_if(option == AGILEREFERENCE_DEFAULT)
548
EXPECT_REF(&unk_obj, 2);
549
550
/* Check the created agile reference object has IAgileObject */
551
hr = IAgileReference_QueryInterface(agile_reference, &IID_IAgileObject, (void **)&agile_object);
552
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
553
IAgileObject_Release(agile_object);
554
555
/* Resolve once */
556
unknown = NULL;
557
hr = IAgileReference_Resolve(agile_reference, &IID_IUnknown, (void **)&unknown);
558
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
559
ok(!!unknown, "Expected pointer not NULL.\n");
560
ok(unknown == &unk_obj.IUnknown_iface, "Expected the same object.\n");
561
todo_wine
562
EXPECT_REF(&unk_obj, 3);
563
564
/* Resolve twice */
565
unknown2 = NULL;
566
hr = IAgileReference_Resolve(agile_reference, &IID_IUnknown, (void **)&unknown2);
567
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
568
ok(!!unknown2, "Expected pointer not NULL.\n");
569
ok(unknown2 == &unk_obj.IUnknown_iface, "Expected the same object.\n");
570
todo_wine
571
EXPECT_REF(&unk_obj, 4);
572
573
/* Resolve in another apartment */
574
for (to_type = RO_INIT_SINGLETHREADED; to_type <= RO_INIT_MULTITHREADED; to_type++)
575
{
576
param.option = option;
577
param.from_type = from_type;
578
param.to_type = to_type;
579
param.agile_reference = agile_reference;
580
param.unk_obj = &unk_obj.IUnknown_iface;
581
param.obj_is_agile = FALSE;
582
thread = CreateThread(NULL, 0, test_RoGetAgileReference_thread_proc, &param, 0, NULL);
583
flush_events();
584
ret = WaitForSingleObject(thread, 100);
585
ok(!ret, "WaitForSingleObject failed, error %ld.\n", GetLastError());
586
}
587
588
IUnknown_Release(unknown2);
589
IUnknown_Release(unknown);
590
IAgileReference_Release(agile_reference);
591
EXPECT_REF(&unk_obj, 1);
592
593
hr = RoGetAgileReference(option, &IID_IUnknown, &unk_agile_obj.IUnknown_iface, &agile_reference);
594
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
595
ok(!!agile_reference, "Got unexpected agile_reference.\n");
596
EXPECT_REF(&unk_agile_obj, 2);
597
598
unknown = NULL;
599
hr = IAgileReference_Resolve(agile_reference, &IID_IUnknown, (void **)&unknown);
600
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
601
ok(!!unknown, "Expected pointer not NULL.\n");
602
ok(unknown == &unk_agile_obj.IUnknown_iface, "Expected the same object.\n");
603
EXPECT_REF(&unk_agile_obj, 3);
604
605
for (to_type = RO_INIT_SINGLETHREADED; to_type <= RO_INIT_MULTITHREADED; to_type++)
606
{
607
param.option = option;
608
param.from_type = from_type;
609
param.to_type = to_type;
610
param.agile_reference = agile_reference;
611
param.unk_obj = &unk_agile_obj.IUnknown_iface;
612
param.obj_is_agile = TRUE;
613
thread = CreateThread(NULL, 0, test_RoGetAgileReference_thread_proc, &param, 0, NULL);
614
flush_events();
615
ret = WaitForSingleObject(thread, 100);
616
ok(!ret, "WaitForSingleObject failed, error %ld.\n", GetLastError());
617
}
618
619
IUnknown_Release(unknown);
620
IAgileReference_Release(agile_reference);
621
EXPECT_REF(&unk_obj, 1);
622
623
RoUninitialize();
624
winetest_pop_context();
625
}
626
}
627
}
628
629
static void test_RoGetErrorReportingFlags(void)
630
{
631
UINT32 flags;
632
HRESULT hr;
633
634
hr = RoGetErrorReportingFlags(NULL);
635
ok(hr == E_POINTER, "Got unexpected hr %#lx.\n", hr);
636
637
hr = RoGetErrorReportingFlags(&flags);
638
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
639
ok(flags == RO_ERROR_REPORTING_USESETERRORINFO, "Got unexpected flag %#x.\n", flags);
640
}
641
642
START_TEST(roapi)
643
{
644
BOOL ret;
645
646
load_resource(L"wine.combase.test.dll");
647
648
test_implicit_mta();
649
test_ActivationFactories();
650
test_RoGetAgileReference();
651
test_RoGetErrorReportingFlags();
652
653
SetLastError(0xdeadbeef);
654
ret = DeleteFileW(L"wine.combase.test.dll");
655
todo_wine_if(!ret && GetLastError() == ERROR_ACCESS_DENIED)
656
ok(ret, "Failed to delete file, error %lu\n", GetLastError());
657
}
658
659