ReactOS 0.4.16-dev-197-g92996da
compobj.c
Go to the documentation of this file.
1/*
2 * COMPOBJ library
3 *
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1998 Justin Bradford
6 * Copyright 1999 Francis Beaudet
7 * Copyright 1999 Sylvain St-Germain
8 * Copyright 2002 Marcus Meissner
9 * Copyright 2004 Mike Hearn
10 * Copyright 2005-2006 Robert Shearman (for CodeWeavers)
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 *
26 * Note
27 * 1. COINIT_MULTITHREADED is 0; it is the lack of COINIT_APARTMENTTHREADED
28 * Therefore do not test against COINIT_MULTITHREADED
29 *
30 * TODO list: (items bunched together depend on each other)
31 *
32 * - Implement the service control manager (in rpcss) to keep track
33 * of registered class objects: ISCM::ServerRegisterClsid et al
34 * - Implement the OXID resolver so we don't need magic endpoint names for
35 * clients and servers to meet up
36 *
37 */
38
39#include <stdarg.h>
40#include <stdio.h>
41#include <string.h>
42#include <assert.h>
43
44#define COBJMACROS
45#define NONAMELESSUNION
46
47#include "ntstatus.h"
48#define WIN32_NO_STATUS
49#include "windef.h"
50#include "winbase.h"
51#include "winerror.h"
52#include "winreg.h"
53#include "winuser.h"
54#define USE_COM_CONTEXT_DEF
55#include "objbase.h"
56#include "ole2.h"
57#include "ole2ver.h"
58#include "ctxtcall.h"
59#include "dde.h"
60#include "servprov.h"
61
62#ifndef __REACTOS__
63#include "initguid.h"
64#endif
65#include "compobj_private.h"
66#include "moniker.h"
67
68#include "wine/debug.h"
69
71
72/****************************************************************************
73 * This section defines variables internal to the COM module.
74 */
75
76static APARTMENT *MTA; /* protected by csApartment */
77static APARTMENT *MainApartment; /* the first STA apartment */
78static struct list apts = LIST_INIT( apts ); /* protected by csApartment */
79
82{
83 0, 0, &csApartment,
85 0, 0, { (DWORD_PTR)(__FILE__ ": csApartment") }
86};
87static CRITICAL_SECTION csApartment = { &critsect_debug, -1, 0, 0, 0, 0 };
88
90{
96};
97
99{
106
108{
129};
130
132{
141};
142
144{
148};
149
151{
152 union
153 {
154 struct
155 {
157 void *section;
161 } u;
163};
164
166{
167 struct list entry;
170};
171
173
176{
179 0, 0, { (DWORD_PTR)(__FILE__ ": cs_registered_psclsid_list") }
180};
182
183/*
184 * This is a marshallable object exposing registered local servers.
185 * IServiceProvider is used only because it happens meet requirements
186 * and already has proxy/stub code. If more functionality is needed,
187 * a custom interface may be used instead.
188 */
190{
195};
196
197/*
198 * This lock count counts the number of times CoInitialize is called. It is
199 * decreased every time CoUninitialize is called. When it hits 0, the COM
200 * libraries are freed
201 */
203/* Reference count used by CoAddRefServerProcess/CoReleaseServerProcess */
205
206/*
207 * This linked list contains the list of registered class objects. These
208 * are mostly used to register the factories for out-of-proc servers of OLE
209 * objects.
210 *
211 * TODO: Make this data structure aware of inter-process communication. This
212 * means that parts of this will be exported to rpcss.
213 */
214typedef struct tagRegisteredClass
215{
216 struct list entry;
225
227
230{
233 0, 0, { (DWORD_PTR)(__FILE__ ": csRegisteredClassList") }
234};
235static CRITICAL_SECTION csRegisteredClassList = { &class_cs_debug, -1, 0, 0, 0, 0 };
236
238{
239 switch (aspect)
240 {
241 case DVASPECT_CONTENT:
242 return MiscStatusContent;
243 case DVASPECT_THUMBNAIL:
244 return MiscStatusThumbnail;
245 case DVASPECT_ICON:
246 return MiscStatusIcon;
247 case DVASPECT_DOCPRINT:
248 return MiscStatusDocPrint;
249 default:
250 return MiscStatus;
251 };
252}
253
255{
256 ACTCTX_SECTION_KEYED_DATA data;
257
258 data.cbSize = sizeof(data);
259 if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,
260 clsid, &data))
261 {
262 struct comclassredirect_data *comclass = (struct comclassredirect_data*)data.lpData;
264
265 if (!(comclass->miscmask & misc))
266 {
267 if (!(comclass->miscmask & MiscStatus))
268 {
269 *status = 0;
270 return TRUE;
271 }
272 misc = MiscStatus;
273 }
274
275 switch (misc)
276 {
277 case MiscStatus:
278 *status = comclass->miscstatus;
279 break;
280 case MiscStatusIcon:
281 *status = comclass->miscstatusicon;
282 break;
284 *status = comclass->miscstatuscontent;
285 break;
287 *status = comclass->miscstatusthumbnail;
288 break;
290 *status = comclass->miscstatusdocprint;
291 break;
292 default:
293 ;
294 };
295
296 return TRUE;
297 }
298 else
299 return FALSE;
300}
301
302/* wrapper for NtCreateKey that creates the key recursively if necessary */
304{
305 NTSTATUS status = NtCreateKey( (HANDLE *)retkey, access, attr, 0, NULL, 0, NULL );
306
308 {
309 HANDLE subkey, root = attr->RootDirectory;
310 WCHAR *buffer = attr->ObjectName->Buffer;
311 DWORD attrs, pos = 0, i = 0, len = attr->ObjectName->Length / sizeof(WCHAR);
313
314 while (i < len && buffer[i] != '\\') i++;
315 if (i == len) return status;
316
317 attrs = attr->Attributes;
318 attr->ObjectName = &str;
319
320 while (i < len)
321 {
322 str.Buffer = buffer + pos;
323 str.Length = (i - pos) * sizeof(WCHAR);
324 status = NtCreateKey( &subkey, access, attr, 0, NULL, 0, NULL );
325 if (attr->RootDirectory != root) NtClose( attr->RootDirectory );
326 if (status) return status;
327 attr->RootDirectory = subkey;
328 while (i < len && buffer[i] == '\\') i++;
329 pos = i;
330 while (i < len && buffer[i] != '\\') i++;
331 }
332 str.Buffer = buffer + pos;
333 str.Length = (i - pos) * sizeof(WCHAR);
334 attr->Attributes = attrs;
335 status = NtCreateKey( (PHANDLE)retkey, access, attr, 0, NULL, 0, NULL );
336 if (attr->RootDirectory != root) NtClose( attr->RootDirectory );
337 }
338 return status;
339}
340
341#ifdef __REACTOS__
342static const WCHAR classes_rootW[] = L"\\REGISTRY\\Machine\\Software\\Classes";
343#else
344static const WCHAR classes_rootW[] =
345 {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e',
346 '\\','S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s',0};
347#endif
348
350
351/* create the special HKEY_CLASSES_ROOT key */
353{
354 HKEY hkey, ret = 0;
357
358 attr.Length = sizeof(attr);
359 attr.RootDirectory = 0;
360 attr.ObjectName = &name;
361 attr.Attributes = 0;
362 attr.SecurityDescriptor = NULL;
363 attr.SecurityQualityOfService = NULL;
365 if (create_key( &hkey, access, &attr )) return 0;
366 TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey );
367
368 if (!(access & KEY_WOW64_64KEY))
369 {
370 if (!(ret = InterlockedCompareExchangePointer( (void **)&classes_root_hkey, hkey, 0 )))
371 ret = hkey;
372 else
373 NtClose( hkey ); /* somebody beat us to it */
374 }
375 else
376 ret = hkey;
377 return ret;
378}
379
380/* map the hkey from special root to normal key if necessary */
382{
383 HKEY ret = hkey;
384 const BOOL is_win64 = sizeof(void*) > sizeof(int);
385 const BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY);
386
387 if (hkey == HKEY_CLASSES_ROOT &&
390 if (force_wow32 && ret && ret == classes_root_hkey)
391 {
392 static const WCHAR wow6432nodeW[] = {'W','o','w','6','4','3','2','N','o','d','e',0};
393 access &= ~KEY_WOW64_32KEY;
394 if (create_classes_key(classes_root_hkey, wow6432nodeW, access, &hkey))
395 return 0;
396 ret = hkey;
397 }
398
399 return ret;
400}
401
403{
406
407 if (!(hkey = get_classes_root_hkey( hkey, access ))) return ERROR_INVALID_HANDLE;
408
409 attr.Length = sizeof(attr);
410 attr.RootDirectory = hkey;
411 attr.ObjectName = &nameW;
412 attr.Attributes = 0;
413 attr.SecurityDescriptor = NULL;
414 attr.SecurityQualityOfService = NULL;
416
417 return RtlNtStatusToDosError( create_key( retkey, access, &attr ) );
418}
419
421{
424
425 if (!(hkey = get_classes_root_hkey( hkey, access ))) return ERROR_INVALID_HANDLE;
426
427 attr.Length = sizeof(attr);
428 attr.RootDirectory = hkey;
429 attr.ObjectName = &nameW;
430 attr.Attributes = 0;
431 attr.SecurityDescriptor = NULL;
432 attr.SecurityQualityOfService = NULL;
434
435 return RtlNtStatusToDosError( NtOpenKey( (HANDLE *)retkey, access, &attr ) );
436}
437
438/*****************************************************************************
439 * This section contains OpenDllList definitions
440 *
441 * The OpenDllList contains only handles of dll loaded by CoGetClassObject or
442 * other functions that do LoadLibrary _without_ giving back a HMODULE.
443 * Without this list these handles would never be freed.
444 *
445 * FIXME: a DLL that says OK when asked for unloading is unloaded in the
446 * next unload-call but not before 600 sec.
447 */
448
451
452typedef struct tagOpenDll
453{
459 struct list entry;
461
463
466{
467 0, 0, &csOpenDllList,
469 0, 0, { (DWORD_PTR)(__FILE__ ": csOpenDllList") }
470};
471static CRITICAL_SECTION csOpenDllList = { &dll_cs_debug, -1, 0, 0, 0, 0 };
472
474{
475 struct list entry;
479};
480
481static const WCHAR wszAptWinClass[] = {'O','l','e','M','a','i','n','T','h','r','e','a','d','W','n','d','C','l','a','s','s',0};
482
484
485/*****************************************************************************
486 * This section contains OpenDllList implementation
487 */
488
490{
491 OpenDll *ptr;
492 OpenDll *ret = NULL;
495 {
496 if (!wcsicmp(library_name, ptr->library_name) &&
497 (InterlockedIncrement(&ptr->refs) != 1) /* entry is being destroy if == 1 */)
498 {
499 ret = ptr;
500 break;
501 }
502 }
504 return ret;
505}
506
507/* caller must ensure that library_name is not already in the open dll list */
509{
510 OpenDll *entry;
511 int len;
512 HRESULT hr = S_OK;
516
517 TRACE("%s\n", debugstr_w(library_name));
518
519 *ret = COMPOBJ_DllList_Get(library_name);
520 if (*ret) return S_OK;
521
522 /* do this outside the csOpenDllList to avoid creating a lock dependency on
523 * the loader lock */
525 if (!hLibrary)
526 {
527 ERR("couldn't load in-process dll %s\n", debugstr_w(library_name));
528 /* failure: DLL could not be loaded */
529 return E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
530 }
531
532 DllCanUnloadNow = (void *)GetProcAddress(hLibrary, "DllCanUnloadNow");
533 /* Note: failing to find DllCanUnloadNow is not a failure */
534 DllGetClassObject = (void *)GetProcAddress(hLibrary, "DllGetClassObject");
536 {
537 /* failure: the dll did not export DllGetClassObject */
538 ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(library_name));
540 return CO_E_DLLNOTFOUND;
541 }
542
544
545 *ret = COMPOBJ_DllList_Get(library_name);
546 if (*ret)
547 {
548 /* another caller to this function already added the dll while we
549 * weren't in the critical section */
551 }
552 else
553 {
554 len = lstrlenW(library_name);
555 entry = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
556 if (entry)
557 entry->library_name = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
558 if (entry && entry->library_name)
559 {
560 memcpy(entry->library_name, library_name, (len + 1)*sizeof(WCHAR));
561 entry->library = hLibrary;
562 entry->refs = 1;
563 entry->DllCanUnloadNow = DllCanUnloadNow;
564 entry->DllGetClassObject = DllGetClassObject;
566 *ret = entry;
567 }
568 else
569 {
573 }
574 }
575
577
578 return hr;
579}
580
581/* pass FALSE for free_entry to release a reference without destroying the
582 * entry if it reaches zero or TRUE otherwise */
584{
585 if (!InterlockedDecrement(&entry->refs) && free_entry)
586 {
588 list_remove(&entry->entry);
590
591 TRACE("freeing %p\n", entry->library);
592 FreeLibrary(entry->library);
593
594 HeapFree(GetProcessHeap(), 0, entry->library_name);
596 }
597}
598
599/* frees memory associated with active dll list */
600static void COMPOBJ_DllList_Free(void)
601{
602 OpenDll *entry, *cursor2;
605 {
606 list_remove(&entry->entry);
607
608 HeapFree(GetProcessHeap(), 0, entry->library_name);
610 }
613}
614
615/******************************************************************************
616 * Manage apartments.
617 */
618
620{
621 DWORD refs = InterlockedIncrement(&apt->refs);
622 TRACE("%s: before = %d\n", wine_dbgstr_longlong(apt->oxid), refs - 1);
623 return refs;
624}
625
626/* allocates memory and fills in the necessary fields for a new apartment
627 * object. must be called inside apartment cs */
629{
630 APARTMENT *apt;
631
632 TRACE("creating new apartment, model=%d\n", model);
633
634 apt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*apt));
635 apt->tid = GetCurrentThreadId();
636
637 list_init(&apt->proxies);
638 list_init(&apt->stubmgrs);
639 list_init(&apt->loaded_dlls);
640 apt->ipidc = 0;
641 apt->refs = 1;
642 apt->remunk_exported = FALSE;
643 apt->oidc = 1;
645 DEBUG_SET_CRITSEC_NAME(&apt->cs, "apartment");
646
648
649 if (apt->multi_threaded)
650 {
651 /* FIXME: should be randomly generated by in an RPC call to rpcss */
652 apt->oxid = ((OXID)GetCurrentProcessId() << 32) | 0xcafe;
653 }
654 else
655 {
656 /* FIXME: should be randomly generated by in an RPC call to rpcss */
657 apt->oxid = ((OXID)GetCurrentProcessId() << 32) | GetCurrentThreadId();
658 }
659
660 TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid));
661
662 list_add_head(&apts, &apt->entry);
663
664 return apt;
665}
666
667/* gets and existing apartment if one exists or otherwise creates an apartment
668 * structure which stores OLE apartment-local information and stores a pointer
669 * to it in the thread-local storage */
671{
672 APARTMENT *apt = COM_CurrentApt();
673
674 if (!apt)
675 {
676 if (model & COINIT_APARTMENTTHREADED)
677 {
679
680 apt = apartment_construct(model);
681 if (!MainApartment)
682 {
683 MainApartment = apt;
684 apt->main = TRUE;
685 TRACE("Created main-threaded apartment with OXID %s\n", wine_dbgstr_longlong(apt->oxid));
686 }
687
689
690 if (apt->main)
692 }
693 else
694 {
696
697 /* The multi-threaded apartment (MTA) contains zero or more threads interacting
698 * with free threaded (ie thread safe) COM objects. There is only ever one MTA
699 * in a process */
700 if (MTA)
701 {
702 TRACE("entering the multithreaded apartment %s\n", wine_dbgstr_longlong(MTA->oxid));
704 }
705 else
706 MTA = apartment_construct(model);
707
708 apt = MTA;
709
711 }
712 COM_CurrentInfo()->apt = apt;
713 }
714
715 return apt;
716}
717
718static inline BOOL apartment_is_model(const APARTMENT *apt, DWORD model)
719{
720 return (apt->multi_threaded == !(model & COINIT_APARTMENTTHREADED));
721}
722
723/* gets the multi-threaded apartment if it exists. The caller must
724 * release the reference from the apartment as soon as the apartment pointer
725 * is no longer required. */
727{
728 APARTMENT *apt;
729
731
732 if ((apt = MTA))
733 apartment_addref(apt);
734
736
737 return apt;
738}
739
740/* Return the current apartment if it exists, or, failing that, the MTA. Caller
741 * must free the returned apartment in either case. */
743{
744 APARTMENT *apt = COM_CurrentApt();
745 if (apt)
746 {
747 apartment_addref(apt);
748 return apt;
749 }
750 return apartment_find_mta();
751}
752
754{
755 list_remove(&curClass->entry);
756
757 if (curClass->runContext & CLSCTX_LOCAL_SERVER)
759
760 IUnknown_Release(curClass->classObject);
761 HeapFree(GetProcessHeap(), 0, curClass);
762}
763
764static void COM_RevokeAllClasses(const struct apartment *apt)
765{
766 RegisteredClass *curClass, *cursor;
767
769
771 {
772 if (curClass->apartment_id == apt->oxid)
774 }
775
777}
778
780{
781 struct registered_psclsid *psclsid, *psclsid2;
782
784
786 {
787 list_remove(&psclsid->entry);
788 HeapFree(GetProcessHeap(), 0, psclsid);
789 }
790
792}
793
794/******************************************************************************
795 * Implementation of the manual reset event object. (CLSID_ManualResetEvent)
796 */
797
798typedef struct ManualResetEvent {
804
806{
807 return CONTAINING_RECORD(iface, MREImpl, ISynchronize_iface);
808}
809
811{
813
814 TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppv);
815
816 if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ISynchronize)) {
817 *ppv = &This->ISynchronize_iface;
818 }else if(IsEqualGUID(riid, &IID_ISynchronizeHandle)) {
819 *ppv = &This->ISynchronizeHandle_iface;
820 }else {
821 ERR("Unknown interface %s requested.\n", debugstr_guid(riid));
822 *ppv = NULL;
823 return E_NOINTERFACE;
824 }
825
826 IUnknown_AddRef((IUnknown*)*ppv);
827 return S_OK;
828}
829
831{
834 TRACE("%p - ref %d\n", This, ref);
835
836 return ref;
837}
838
840{
843 TRACE("%p - ref %d\n", This, ref);
844
845 if(!ref)
846 {
847 CloseHandle(This->event);
849 }
850
851 return ref;
852}
853
855{
857 UINT index;
858 TRACE("%p (%08x, %08x)\n", This, dwFlags, dwMilliseconds);
859 return CoWaitForMultipleHandles(dwFlags, dwMilliseconds, 1, &This->event, &index);
860}
861
863{
865 TRACE("%p\n", This);
866 SetEvent(This->event);
867 return S_OK;
868}
869
871{
873 TRACE("%p\n", This);
874 ResetEvent(This->event);
875 return S_OK;
876}
877
878static ISynchronizeVtbl vt_ISynchronize = {
885};
886
888{
889 return CONTAINING_RECORD(iface, MREImpl, ISynchronizeHandle_iface);
890}
891
893{
895 return ISynchronize_QueryInterface(&This->ISynchronize_iface, riid, ppv);
896}
897
899{
901 return ISynchronize_AddRef(&This->ISynchronize_iface);
902}
903
905{
907 return ISynchronize_Release(&This->ISynchronize_iface);
908}
909
911{
913
914 *ph = This->event;
915 return S_OK;
916}
917
918static const ISynchronizeHandleVtbl SynchronizeHandleVtbl = {
923};
924
925static HRESULT ManualResetEvent_Construct(IUnknown *punkouter, REFIID iid, void **ppv)
926{
928 HRESULT hr;
929
930 if(punkouter)
931 FIXME("Aggregation not implemented.\n");
932
933 This->ref = 1;
934 This->ISynchronize_iface.lpVtbl = &vt_ISynchronize;
935 This->ISynchronizeHandle_iface.lpVtbl = &SynchronizeHandleVtbl;
936 This->event = CreateEventW(NULL, TRUE, FALSE, NULL);
937
938 hr = ISynchronize_QueryInterface(&This->ISynchronize_iface, iid, ppv);
939 ISynchronize_Release(&This->ISynchronize_iface);
940 return hr;
941}
942
944{
945 return CONTAINING_RECORD(iface, LocalServer, IServiceProvider_iface);
946}
947
949{
951
952 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
953
954 if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IServiceProvider)) {
955 *ppv = &This->IServiceProvider_iface;
956 }else {
957 *ppv = NULL;
958 return E_NOINTERFACE;
959 }
960
961 IUnknown_AddRef((IUnknown*)*ppv);
962 return S_OK;
963}
964
966{
969
970 TRACE("(%p) ref=%d\n", This, ref);
971
972 return ref;
973}
974
976{
979
980 TRACE("(%p) ref=%d\n", This, ref);
981
982 if(!ref) {
983 assert(!This->apt);
985 }
986
987 return ref;
988}
989
991{
993 APARTMENT *apt = COM_CurrentApt();
994 RegisteredClass *iter;
996
997 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guid), debugstr_guid(riid), ppv);
998
999 if(!This->apt)
1000 return E_UNEXPECTED;
1001
1003
1005 if(iter->apartment_id == apt->oxid
1006 && (iter->runContext & CLSCTX_LOCAL_SERVER)
1007 && IsEqualGUID(&iter->classIdentifier, guid)) {
1008 hres = IUnknown_QueryInterface(iter->classObject, riid, ppv);
1009 break;
1010 }
1011 }
1012
1014
1015 return hres;
1016}
1017
1018static const IServiceProviderVtbl LocalServerVtbl = {
1023};
1024
1026{
1027 HRESULT hres = S_OK;
1028
1029 EnterCriticalSection(&apt->cs);
1030
1031 if(!apt->local_server) {
1033
1034 obj = heap_alloc(sizeof(*obj));
1035 if(obj) {
1036 obj->IServiceProvider_iface.lpVtbl = &LocalServerVtbl;
1037 obj->ref = 1;
1038 obj->apt = apt;
1039
1040 hres = CreateStreamOnHGlobal(0, TRUE, &obj->marshal_stream);
1041 if(SUCCEEDED(hres)) {
1042 hres = CoMarshalInterface(obj->marshal_stream, &IID_IServiceProvider, (IUnknown*)&obj->IServiceProvider_iface,
1043 MSHCTX_LOCAL, NULL, MSHLFLAGS_TABLESTRONG);
1044 if(FAILED(hres))
1045 IStream_Release(obj->marshal_stream);
1046 }
1047
1048 if(SUCCEEDED(hres))
1049 apt->local_server = obj;
1050 else
1051 heap_free(obj);
1052 }else {
1054 }
1055 }
1056
1057 if(SUCCEEDED(hres))
1058 hres = IStream_Clone(apt->local_server->marshal_stream, ret);
1059
1060 LeaveCriticalSection(&apt->cs);
1061
1062 if(FAILED(hres))
1063 ERR("Failed: %08x\n", hres);
1064 return hres;
1065}
1066
1067/***********************************************************************
1068 * CoRevokeClassObject [OLE32.@]
1069 *
1070 * Removes a class object from the class registry.
1071 *
1072 * PARAMS
1073 * dwRegister [I] Cookie returned from CoRegisterClassObject().
1074 *
1075 * RETURNS
1076 * Success: S_OK.
1077 * Failure: HRESULT code.
1078 *
1079 * NOTES
1080 * Must be called from the same apartment that called CoRegisterClassObject(),
1081 * otherwise it will fail with RPC_E_WRONG_THREAD.
1082 *
1083 * SEE ALSO
1084 * CoRegisterClassObject
1085 */
1087 DWORD dwRegister)
1088{
1090 RegisteredClass *curClass;
1091 APARTMENT *apt;
1092
1093 TRACE("(%08x)\n",dwRegister);
1094
1095 if (!(apt = apartment_get_current_or_mta()))
1096 {
1097 ERR("COM was not initialized\n");
1098 return CO_E_NOTINITIALIZED;
1099 }
1100
1102
1104 {
1105 /*
1106 * Check if we have a match on the cookie.
1107 */
1108 if (curClass->dwCookie == dwRegister)
1109 {
1110 if (curClass->apartment_id == apt->oxid)
1111 {
1113 hr = S_OK;
1114 }
1115 else
1116 {
1117 ERR("called from wrong apartment, should be called from %s\n",
1120 }
1121 break;
1122 }
1123 }
1124
1126 apartment_release(apt);
1127 return hr;
1128}
1129
1130/* frees unused libraries loaded by apartment_getclassobject by calling the
1131 * DLL's DllCanUnloadNow entry point */
1132static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay)
1133{
1135 EnterCriticalSection(&apt->cs);
1137 {
1138 if (entry->dll->DllCanUnloadNow && (entry->dll->DllCanUnloadNow() == S_OK))
1139 {
1140 DWORD real_delay = delay;
1141
1142 if (real_delay == INFINITE)
1143 {
1144 /* DLLs that return multi-threaded objects aren't unloaded
1145 * straight away to cope for programs that have races between
1146 * last object destruction and threads in the DLLs that haven't
1147 * finished, despite DllCanUnloadNow returning S_OK */
1148 if (entry->multi_threaded)
1149 real_delay = 10 * 60 * 1000; /* 10 minutes */
1150 else
1151 real_delay = 0;
1152 }
1153
1154 if (!real_delay || (entry->unload_time && ((int)(GetTickCount() - entry->unload_time) > 0)))
1155 {
1156 list_remove(&entry->entry);
1159 }
1160 else
1161 {
1162 entry->unload_time = GetTickCount() + real_delay;
1163 if (!entry->unload_time) entry->unload_time = 1;
1164 }
1165 }
1166 else if (entry->unload_time)
1167 entry->unload_time = 0;
1168 }
1169 LeaveCriticalSection(&apt->cs);
1170}
1171
1173{
1174 DWORD ret;
1175
1177
1178 ret = InterlockedDecrement(&apt->refs);
1179 TRACE("%s: after = %d\n", wine_dbgstr_longlong(apt->oxid), ret);
1180
1181 if (apt->being_destroyed)
1182 {
1184 return ret;
1185 }
1186
1187 /* destruction stuff that needs to happen under csApartment CS */
1188 if (ret == 0)
1189 {
1190 apt->being_destroyed = TRUE;
1191 if (apt == MTA) MTA = NULL;
1192 else if (apt == MainApartment) MainApartment = NULL;
1193 list_remove(&apt->entry);
1194 }
1195
1197
1198 if (ret == 0)
1199 {
1200 struct list *cursor, *cursor2;
1201
1202 TRACE("destroying apartment %p, oxid %s\n", apt, wine_dbgstr_longlong(apt->oxid));
1203
1204 if(apt->local_server) {
1207
1208 memset(&zero, 0, sizeof(zero));
1209 IStream_Seek(local_server->marshal_stream, zero, STREAM_SEEK_SET, NULL);
1210 CoReleaseMarshalData(local_server->marshal_stream);
1211 IStream_Release(local_server->marshal_stream);
1212 local_server->marshal_stream = NULL;
1213
1214 apt->local_server = NULL;
1215 local_server->apt = NULL;
1216 IServiceProvider_Release(&local_server->IServiceProvider_iface);
1217 }
1218
1219 /* Release the references to the registered class objects */
1221
1222 /* no locking is needed for this apartment, because no other thread
1223 * can access it at this point */
1224
1226
1227 if (apt->win) DestroyWindow(apt->win);
1228 if (apt->host_apt_tid) PostThreadMessageW(apt->host_apt_tid, WM_QUIT, 0, 0);
1229
1230 LIST_FOR_EACH_SAFE(cursor, cursor2, &apt->stubmgrs)
1231 {
1232 struct stub_manager *stubmgr = LIST_ENTRY(cursor, struct stub_manager, entry);
1233 /* release the implicit reference given by the fact that the
1234 * stub has external references (it must do since it is in the
1235 * stub manager list in the apartment and all non-apartment users
1236 * must have a ref on the apartment and so it cannot be destroyed).
1237 */
1238 stub_manager_int_release(stubmgr);
1239 }
1240
1241 /* if this assert fires, then another thread took a reference to a
1242 * stub manager without taking a reference to the containing
1243 * apartment, which it must do. */
1245
1246 if (apt->filter) IMessageFilter_Release(apt->filter);
1247
1248 /* free as many unused libraries as possible... */
1250
1251 /* ... and free the memory for the apartment loaded dll entry and
1252 * release the dll list reference without freeing the library for the
1253 * rest */
1254 while ((cursor = list_head(&apt->loaded_dlls)))
1255 {
1260 }
1261
1264
1265 HeapFree(GetProcessHeap(), 0, apt);
1266 }
1267
1268 return ret;
1269}
1270
1271/* The given OXID must be local to this process:
1272 *
1273 * The ref parameter is here mostly to ensure people remember that
1274 * they get one, you should normally take a ref for thread safety.
1275 */
1277{
1279 struct list *cursor;
1280
1283 {
1284 struct apartment *apt = LIST_ENTRY( cursor, struct apartment, entry );
1285 if (apt->oxid == oxid)
1286 {
1287 result = apt;
1289 break;
1290 }
1291 }
1293
1294 return result;
1295}
1296
1297/* gets the apartment which has a given creator thread ID. The caller must
1298 * release the reference from the apartment as soon as the apartment pointer
1299 * is no longer required. */
1301{
1303 struct list *cursor;
1304
1307 {
1308 struct apartment *apt = LIST_ENTRY( cursor, struct apartment, entry );
1309 if (apt->tid == tid)
1310 {
1311 result = apt;
1313 break;
1314 }
1315 }
1317
1318 return result;
1319}
1320
1321/* gets the main apartment if it exists. The caller must
1322 * release the reference from the apartment as soon as the apartment pointer
1323 * is no longer required. */
1325{
1327
1329
1332
1334
1335 return result;
1336}
1337
1338/* gets the specified class object by loading the appropriate DLL, if
1339 * necessary and calls the DllGetClassObject function for the DLL */
1341 BOOL apartment_threaded,
1342 REFCLSID rclsid, REFIID riid, void **ppv)
1343{
1344 static const WCHAR wszOle32[] = {'o','l','e','3','2','.','d','l','l',0};
1345 HRESULT hr = S_OK;
1346 BOOL found = FALSE;
1348
1349 if (!wcsicmp(dllpath, wszOle32))
1350 {
1351 /* we don't need to control the lifetime of this dll, so use the local
1352 * implementation of DllGetClassObject directly */
1353 TRACE("calling ole32!DllGetClassObject\n");
1354 hr = DllGetClassObject(rclsid, riid, ppv);
1355
1356 if (hr != S_OK)
1357 ERR("DllGetClassObject returned error 0x%08x for dll %s\n", hr, debugstr_w(dllpath));
1358
1359 return hr;
1360 }
1361
1362 EnterCriticalSection(&apt->cs);
1363
1366 {
1367 TRACE("found %s already loaded\n", debugstr_w(dllpath));
1368 found = TRUE;
1369 break;
1370 }
1371
1372 if (!found)
1373 {
1376 hr = E_OUTOFMEMORY;
1377 if (SUCCEEDED(hr))
1378 {
1382 if (FAILED(hr))
1384 }
1385 if (SUCCEEDED(hr))
1386 {
1387 TRACE("added new loaded dll %s\n", debugstr_w(dllpath));
1389 }
1390 }
1391
1392 LeaveCriticalSection(&apt->cs);
1393
1394 if (SUCCEEDED(hr))
1395 {
1396 /* one component being multi-threaded overrides any number of
1397 * apartment-threaded components */
1398 if (!apartment_threaded)
1400
1401 TRACE("calling DllGetClassObject %p\n", apartment_loaded_dll->dll->DllGetClassObject);
1402 /* OK: get the ClassObject */
1404
1405 if (hr != S_OK)
1406 ERR("DllGetClassObject returned error 0x%08x for dll %s\n", hr, debugstr_w(dllpath));
1407 }
1408
1409 return hr;
1410}
1411
1412/* Returns expanded dll path from the registry or activation context. */
1414{
1415 DWORD ret;
1416
1417 if (regdata->hkey)
1418 {
1419 DWORD keytype;
1421 DWORD dwLength = dstlen * sizeof(WCHAR);
1422
1423 if( (ret = RegQueryValueExW(regdata->u.hkey, NULL, NULL, &keytype, (BYTE*)src, &dwLength)) == ERROR_SUCCESS ) {
1424 if (keytype == REG_EXPAND_SZ) {
1426 } else {
1427 const WCHAR *quote_start;
1428 quote_start = wcschr(src, '\"');
1429 if (quote_start) {
1430 const WCHAR *quote_end = wcschr(quote_start + 1, '\"');
1431 if (quote_end) {
1432 memmove(src, quote_start + 1,
1433 (quote_end - quote_start - 1) * sizeof(WCHAR));
1434 src[quote_end - quote_start - 1] = '\0';
1435 }
1436 }
1438 }
1439 }
1440 return !ret;
1441 }
1442 else
1443 {
1444 static const WCHAR dllW[] = {'.','d','l','l',0};
1446 WCHAR *nameW;
1447
1448 *dst = 0;
1449 nameW = (WCHAR*)((BYTE*)regdata->u.actctx.section + regdata->u.actctx.data->name_offset);
1450 ActivateActCtx(regdata->u.actctx.hactctx, &cookie);
1453 return *dst != 0;
1454 }
1455}
1456
1458{
1460 CLSID clsid; /* clsid of object to marshal */
1461 IID iid; /* interface to marshal */
1462 HANDLE event; /* event signalling when ready for multi-threaded case */
1463 HRESULT hr; /* result for multi-threaded case */
1464 IStream *stream; /* stream that the object will be marshaled into */
1465 BOOL apartment_threaded; /* is the component purely apartment-threaded? */
1466};
1467
1469 const struct host_object_params *params)
1470{
1472 HRESULT hr;
1473 static const LARGE_INTEGER llZero;
1475
1476 TRACE("clsid %s, iid %s\n", debugstr_guid(&params->clsid), debugstr_guid(&params->iid));
1477
1479 {
1480 /* failure: CLSID is not found in registry */
1481 WARN("class %s not registered inproc\n", debugstr_guid(&params->clsid));
1482 return REGDB_E_CLASSNOTREG;
1483 }
1484
1485 hr = apartment_getclassobject(apt, dllpath, params->apartment_threaded,
1486 &params->clsid, &params->iid, (void **)&object);
1487 if (FAILED(hr))
1488 return hr;
1489
1490 hr = CoMarshalInterface(params->stream, &params->iid, object, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1491 if (FAILED(hr))
1492 IUnknown_Release(object);
1493 IStream_Seek(params->stream, llZero, STREAM_SEEK_SET, NULL);
1494
1495 return hr;
1496}
1497
1499{
1500 switch (msg)
1501 {
1502 case DM_EXECUTERPC:
1504 return 0;
1505 case DM_HOSTOBJECT:
1507 default:
1508 return DefWindowProcW(hWnd, msg, wParam, lParam);
1509 }
1510}
1511
1513{
1517};
1518
1519/* thread for hosting an object to allow an object to appear to be created in
1520 * an apartment with an incompatible threading model */
1522{
1523 struct host_thread_params *params = p;
1524 MSG msg;
1525 HRESULT hr;
1526 struct apartment *apt;
1527
1528 TRACE("\n");
1529
1530 hr = CoInitializeEx(NULL, params->threading_model);
1531 if (FAILED(hr)) return hr;
1532
1533 apt = COM_CurrentApt();
1534 if (params->threading_model == COINIT_APARTMENTTHREADED)
1535 {
1537 params->apartment_hwnd = apartment_getwindow(apt);
1538 }
1539 else
1540 params->apartment_hwnd = NULL;
1541
1542 /* force the message queue to be created before signaling parent thread */
1544
1545 SetEvent(params->ready_event);
1546 params = NULL; /* can't touch params after here as it may be invalid */
1547
1548 while (GetMessageW(&msg, NULL, 0, 0))
1549 {
1550 if (!msg.hwnd && (msg.message == DM_HOSTOBJECT))
1551 {
1552 struct host_object_params *obj_params = (struct host_object_params *)msg.lParam;
1553 obj_params->hr = apartment_hostobject(apt, obj_params);
1554 SetEvent(obj_params->event);
1555 }
1556 else
1557 {
1560 }
1561 }
1562
1563 TRACE("exiting\n");
1564
1566
1567 return S_OK;
1568}
1569
1570/* finds or creates a host apartment, creates the object inside it and returns
1571 * a proxy to it so that the object can be used in the apartment of the
1572 * caller of this function */
1574 struct apartment *apt, BOOL multi_threaded, BOOL main_apartment,
1575 const struct class_reg_data *regdata, REFCLSID rclsid, REFIID riid, void **ppv)
1576{
1578 HWND apartment_hwnd = NULL;
1579 DWORD apartment_tid = 0;
1580 HRESULT hr;
1581
1582 if (!multi_threaded && main_apartment)
1583 {
1584 APARTMENT *host_apt = apartment_findmain();
1585 if (host_apt)
1586 {
1587 apartment_hwnd = apartment_getwindow(host_apt);
1588 apartment_release(host_apt);
1589 }
1590 }
1591
1592 if (!apartment_hwnd)
1593 {
1594 EnterCriticalSection(&apt->cs);
1595
1596 if (!apt->host_apt_tid)
1597 {
1598 struct host_thread_params thread_params;
1599 HANDLE handles[2];
1600 DWORD wait_value;
1601
1602 thread_params.threading_model = multi_threaded ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED;
1603 handles[0] = thread_params.ready_event = CreateEventW(NULL, FALSE, FALSE, NULL);
1604 thread_params.apartment_hwnd = NULL;
1605 handles[1] = CreateThread(NULL, 0, apartment_hostobject_thread, &thread_params, 0, &apt->host_apt_tid);
1606 if (!handles[1])
1607 {
1608 CloseHandle(handles[0]);
1609 LeaveCriticalSection(&apt->cs);
1610 return E_OUTOFMEMORY;
1611 }
1612 wait_value = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
1613 CloseHandle(handles[0]);
1614 CloseHandle(handles[1]);
1615 if (wait_value == WAIT_OBJECT_0)
1616 apt->host_apt_hwnd = thread_params.apartment_hwnd;
1617 else
1618 {
1619 LeaveCriticalSection(&apt->cs);
1620 return E_OUTOFMEMORY;
1621 }
1622 }
1623
1624 if (multi_threaded || !main_apartment)
1625 {
1627 apartment_tid = apt->host_apt_tid;
1628 }
1629
1630 LeaveCriticalSection(&apt->cs);
1631 }
1632
1633 /* another thread may have become the main apartment in the time it took
1634 * us to create the thread for the host apartment */
1635 if (!apartment_hwnd && !multi_threaded && main_apartment)
1636 {
1637 APARTMENT *host_apt = apartment_findmain();
1638 if (host_apt)
1639 {
1641 apartment_release(host_apt);
1642 }
1643 }
1644
1645 params.regdata = *regdata;
1646 params.clsid = *rclsid;
1647 params.iid = *riid;
1649 if (FAILED(hr))
1650 return hr;
1651 params.apartment_threaded = !multi_threaded;
1652 if (multi_threaded)
1653 {
1654 params.hr = S_OK;
1655 params.event = CreateEventW(NULL, FALSE, FALSE, NULL);
1656 if (!PostThreadMessageW(apartment_tid, DM_HOSTOBJECT, 0, (LPARAM)&params))
1657 hr = E_OUTOFMEMORY;
1658 else
1659 {
1661 hr = params.hr;
1662 }
1663 CloseHandle(params.event);
1664 }
1665 else
1666 {
1667 if (!apartment_hwnd)
1668 {
1669 ERR("host apartment didn't create window\n");
1670 hr = E_OUTOFMEMORY;
1671 }
1672 else
1674 }
1675 if (SUCCEEDED(hr))
1677 IStream_Release(params.stream);
1678 return hr;
1679}
1680
1681static BOOL WINAPI register_class( INIT_ONCE *once, void *param, void **context )
1682{
1683 WNDCLASSW wclass;
1684
1685 /* Dispatching to the correct thread in an apartment is done through
1686 * window messages rather than RPC transports. When an interface is
1687 * marshalled into another apartment in the same process, a window of the
1688 * following class is created. The *caller* of CoMarshalInterface (i.e., the
1689 * application) is responsible for pumping the message loop in that thread.
1690 * The WM_USER messages which point to the RPCs are then dispatched to
1691 * apartment_wndproc by the user's code from the apartment in which the
1692 * interface was unmarshalled.
1693 */
1694 memset(&wclass, 0, sizeof(wclass));
1696 wclass.hInstance = hProxyDll;
1698 apt_win_class = RegisterClassW(&wclass);
1699 return TRUE;
1700}
1701
1702/* create a window for the apartment or return the current one if one has
1703 * already been created */
1705{
1706 static INIT_ONCE class_init_once = INIT_ONCE_STATIC_INIT;
1707
1708 if (apt->multi_threaded)
1709 return S_OK;
1710
1711 if (!apt->win)
1712 {
1713 HWND hwnd;
1714
1715 InitOnceExecuteOnce( &class_init_once, register_class, NULL, NULL );
1716
1717 hwnd = CreateWindowW(wszAptWinClass, NULL, 0, 0, 0, 0, 0,
1718 HWND_MESSAGE, 0, hProxyDll, NULL);
1719 if (!hwnd)
1720 {
1721 ERR("CreateWindow failed with error %d\n", GetLastError());
1723 }
1725 /* someone beat us to it */
1727 }
1728
1729 return S_OK;
1730}
1731
1732/* retrieves the window for the main- or apartment-threaded apartment */
1734{
1735 assert(!apt->multi_threaded);
1736 return apt->win;
1737}
1738
1739static void COM_TlsDestroy(void)
1740{
1741 struct oletls *info = NtCurrentTeb()->ReservedForOle;
1742 if (info)
1743 {
1744 struct init_spy *cursor, *cursor2;
1745
1746 if (info->apt) apartment_release(info->apt);
1747 if (info->errorinfo) IErrorInfo_Release(info->errorinfo);
1748 if (info->state) IUnknown_Release(info->state);
1749
1750 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &info->spies, struct init_spy, entry)
1751 {
1752 list_remove(&cursor->entry);
1753 if (cursor->spy) IInitializeSpy_Release(cursor->spy);
1755 }
1756
1757 if (info->context_token) IObjContext_Release(info->context_token);
1758
1760 NtCurrentTeb()->ReservedForOle = NULL;
1761 }
1762}
1763
1764/******************************************************************************
1765 * CoBuildVersion [OLE32.@]
1766 *
1767 * Gets the build version of the DLL.
1768 *
1769 * PARAMS
1770 *
1771 * RETURNS
1772 * Current build version, hiword is majornumber, loword is minornumber
1773 */
1775{
1776 TRACE("Returning version %d, build %d.\n", rmm, rup);
1777 return (rmm<<16)+rup;
1778}
1779
1780static struct init_spy *get_spy_entry(struct oletls *info, unsigned int id)
1781{
1782 struct init_spy *spy;
1783
1784 LIST_FOR_EACH_ENTRY(spy, &info->spies, struct init_spy, entry)
1785 {
1786 if (id == spy->id && spy->spy)
1787 return spy;
1788 }
1789
1790 return NULL;
1791}
1792
1793/*
1794 * When locked, don't modify list (unless we add a new head), so that it's
1795 * safe to iterate it. Freeing of list entries is delayed and done on unlock.
1796 */
1797static inline void lock_init_spies(struct oletls *info)
1798{
1799 info->spies_lock++;
1800}
1801
1802static void unlock_init_spies(struct oletls *info)
1803{
1804 struct init_spy *spy, *next;
1805
1806 if (--info->spies_lock) return;
1807
1809 {
1810 if (spy->spy) continue;
1811 list_remove(&spy->entry);
1812 heap_free(spy);
1813 }
1814}
1815
1816/******************************************************************************
1817 * CoRegisterInitializeSpy [OLE32.@]
1818 *
1819 * Add a Spy that watches CoInitializeEx calls
1820 *
1821 * PARAMS
1822 * spy [I] Pointer to IUnknown interface that will be QueryInterface'd.
1823 * cookie [II] cookie receiver
1824 *
1825 * RETURNS
1826 * Success: S_OK if not already initialized, S_FALSE otherwise.
1827 * Failure: HRESULT code.
1828 *
1829 * SEE ALSO
1830 * CoInitializeEx
1831 */
1833{
1834 struct oletls *info = COM_CurrentInfo();
1835 struct init_spy *entry;
1836 unsigned int id;
1837 HRESULT hr;
1838
1839 TRACE("(%p, %p)\n", spy, cookie);
1840
1841 if (!spy || !cookie || !info)
1842 {
1843 if (!info)
1844 WARN("Could not allocate tls\n");
1845 return E_INVALIDARG;
1846 }
1847
1848 hr = IInitializeSpy_QueryInterface(spy, &IID_IInitializeSpy, (void **)&spy);
1849 if (FAILED(hr))
1850 return hr;
1851
1852 entry = heap_alloc(sizeof(*entry));
1853 if (!entry)
1854 {
1855 IInitializeSpy_Release(spy);
1856 return E_OUTOFMEMORY;
1857 }
1858
1859 entry->spy = spy;
1860
1861 id = 0;
1862 while (get_spy_entry(info, id) != NULL)
1863 {
1864 id++;
1865 }
1866
1867 entry->id = id;
1868 list_add_head(&info->spies, &entry->entry);
1869
1870 cookie->s.HighPart = GetCurrentThreadId();
1871 cookie->s.LowPart = entry->id;
1872
1873 return S_OK;
1874}
1875
1876/******************************************************************************
1877 * CoRevokeInitializeSpy [OLE32.@]
1878 *
1879 * Remove a spy that previously watched CoInitializeEx calls
1880 *
1881 * PARAMS
1882 * cookie [I] The cookie obtained from a previous CoRegisterInitializeSpy call
1883 *
1884 * RETURNS
1885 * Success: S_OK if a spy is removed
1886 * Failure: E_INVALIDARG
1887 *
1888 * SEE ALSO
1889 * CoInitializeEx
1890 */
1892{
1893 struct oletls *info = COM_CurrentInfo();
1894 struct init_spy *spy;
1895
1896 TRACE("(%s)\n", wine_dbgstr_longlong(cookie.QuadPart));
1897
1898 if (!info || cookie.s.HighPart != GetCurrentThreadId())
1899 return E_INVALIDARG;
1900
1901 if (!(spy = get_spy_entry(info, cookie.s.LowPart))) return E_INVALIDARG;
1902
1903 IInitializeSpy_Release(spy->spy);
1904 spy->spy = NULL;
1905 if (!info->spies_lock)
1906 {
1907 list_remove(&spy->entry);
1908 heap_free(spy);
1909 }
1910 return S_OK;
1911}
1912
1914{
1915 HRESULT hr = S_OK;
1916
1917 if (!info->apt)
1918 {
1919 if (!apartment_get_or_create( model ))
1920 return E_OUTOFMEMORY;
1921 }
1922 else if (!apartment_is_model( info->apt, model ))
1923 {
1924 WARN( "Attempt to change threading model of this apartment from %s to %s\n",
1925 info->apt->multi_threaded ? "multi-threaded" : "apartment threaded",
1926 model & COINIT_APARTMENTTHREADED ? "apartment threaded" : "multi-threaded" );
1927 return RPC_E_CHANGED_MODE;
1928 }
1929 else
1930 hr = S_FALSE;
1931
1932 info->inits++;
1933
1934 return hr;
1935}
1936
1938{
1939 if (!--info->inits)
1940 {
1941 if (info->ole_inits)
1942 WARN( "Uninitializing apartment while Ole is still initialized\n" );
1943 apartment_release( info->apt );
1944 info->apt = NULL;
1945 }
1946}
1947
1948/******************************************************************************
1949 * CoInitialize [OLE32.@]
1950 *
1951 * Initializes the COM libraries by calling CoInitializeEx with
1952 * COINIT_APARTMENTTHREADED, ie it enters a STA thread.
1953 *
1954 * PARAMS
1955 * lpReserved [I] Pointer to IMalloc interface (obsolete, should be NULL).
1956 *
1957 * RETURNS
1958 * Success: S_OK if not already initialized, S_FALSE otherwise.
1959 * Failure: HRESULT code.
1960 *
1961 * SEE ALSO
1962 * CoInitializeEx
1963 */
1965{
1966 /*
1967 * Just delegate to the newer method.
1968 */
1969 return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
1970}
1971
1972/******************************************************************************
1973 * CoInitializeEx [OLE32.@]
1974 *
1975 * Initializes the COM libraries.
1976 *
1977 * PARAMS
1978 * lpReserved [I] Pointer to IMalloc interface (obsolete, should be NULL).
1979 * dwCoInit [I] One or more flags from the COINIT enumeration. See notes.
1980 *
1981 * RETURNS
1982 * S_OK if successful,
1983 * S_FALSE if this function was called already.
1984 * RPC_E_CHANGED_MODE if a previous call to CoInitializeEx specified another
1985 * threading model.
1986 *
1987 * NOTES
1988 *
1989 * The behavior used to set the IMalloc used for memory management is
1990 * obsolete.
1991 * The dwCoInit parameter must specify one of the following apartment
1992 * threading models:
1993 *| COINIT_APARTMENTTHREADED - A single-threaded apartment (STA).
1994 *| COINIT_MULTITHREADED - A multi-threaded apartment (MTA).
1995 * The parameter may also specify zero or more of the following flags:
1996 *| COINIT_DISABLE_OLE1DDE - Don't use DDE for OLE1 support.
1997 *| COINIT_SPEED_OVER_MEMORY - Trade memory for speed.
1998 *
1999 * SEE ALSO
2000 * CoUninitialize
2001 */
2003{
2004 struct oletls *info = COM_CurrentInfo();
2005 struct init_spy *cursor;
2006 HRESULT hr;
2007
2008 TRACE("(%p, %x)\n", lpReserved, (int)dwCoInit);
2009
2010 if (lpReserved!=NULL)
2011 {
2012 ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved);
2013 }
2014
2015 /*
2016 * Check the lock count. If this is the first time going through the initialize
2017 * process, we have to initialize the libraries.
2018 *
2019 * And crank-up that lock count.
2020 */
2022 {
2023 /*
2024 * Initialize the various COM libraries and data structures.
2025 */
2026 TRACE("() - Initializing the COM libraries\n");
2027
2028 /* we may need to defer this until after apartment initialisation */
2030 }
2031
2033 LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry)
2034 {
2035 if (cursor->spy) IInitializeSpy_PreInitialize(cursor->spy, dwCoInit, info->inits);
2036 }
2038
2040
2042 LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry)
2043 {
2044 if (cursor->spy) hr = IInitializeSpy_PostInitialize(cursor->spy, hr, dwCoInit, info->inits);
2045 }
2047
2048 return hr;
2049}
2050
2051/***********************************************************************
2052 * CoUninitialize [OLE32.@]
2053 *
2054 * This method will decrement the refcount on the current apartment, freeing
2055 * the resources associated with it if it is the last thread in the apartment.
2056 * If the last apartment is freed, the function will additionally release
2057 * any COM resources associated with the process.
2058 *
2059 * PARAMS
2060 *
2061 * RETURNS
2062 * Nothing.
2063 *
2064 * SEE ALSO
2065 * CoInitializeEx
2066 */
2068{
2069 struct oletls * info = COM_CurrentInfo();
2070 struct init_spy *cursor, *next;
2071 LONG lCOMRefCnt;
2072
2073 TRACE("()\n");
2074
2075 /* will only happen on OOM */
2076 if (!info) return;
2077
2080 {
2081 if (cursor->spy) IInitializeSpy_PreUninitialize(cursor->spy, info->inits);
2082 }
2084
2085 /* sanity check */
2086 if (!info->inits)
2087 {
2088 ERR("Mismatched CoUninitialize\n");
2089
2092 {
2093 if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, info->inits);
2094 }
2096
2097 return;
2098 }
2099
2101
2102 /*
2103 * Decrease the reference count.
2104 * If we are back to 0 locks on the COM library, make sure we free
2105 * all the associated data structures.
2106 */
2107 lCOMRefCnt = InterlockedExchangeAdd(&s_COMLockCount,-1);
2108 if (lCOMRefCnt==1)
2109 {
2110 TRACE("() - Releasing the COM libraries\n");
2111
2114 }
2115 else if (lCOMRefCnt<1) {
2116 ERR( "CoUninitialize() - not CoInitialized.\n" );
2117 InterlockedExchangeAdd(&s_COMLockCount,1); /* restore the lock count. */
2118 }
2119
2121 LIST_FOR_EACH_ENTRY(cursor, &info->spies, struct init_spy, entry)
2122 {
2123 if (cursor->spy) IInitializeSpy_PostUninitialize(cursor->spy, info->inits);
2124 }
2126}
2127
2128/******************************************************************************
2129 * CoDisconnectObject [OLE32.@]
2130 *
2131 * Disconnects all connections to this object from remote processes. Dispatches
2132 * pending RPCs while blocking new RPCs from occurring, and then calls
2133 * IMarshal::DisconnectObject on the given object.
2134 *
2135 * Typically called when the object server is forced to shut down, for instance by
2136 * the user.
2137 *
2138 * PARAMS
2139 * lpUnk [I] The object whose stub should be disconnected.
2140 * reserved [I] Reserved. Should be set to 0.
2141 *
2142 * RETURNS
2143 * Success: S_OK.
2144 * Failure: HRESULT code.
2145 *
2146 * SEE ALSO
2147 * CoMarshalInterface, CoReleaseMarshalData, CoLockObjectExternal
2148 */
2150{
2151 struct stub_manager *manager;
2152 HRESULT hr;
2153 IMarshal *marshal;
2154 APARTMENT *apt;
2155
2156 TRACE("(%p, 0x%08x)\n", lpUnk, reserved);
2157
2158 if (!lpUnk) return E_INVALIDARG;
2159
2160 hr = IUnknown_QueryInterface(lpUnk, &IID_IMarshal, (void **)&marshal);
2161 if (hr == S_OK)
2162 {
2163 hr = IMarshal_DisconnectObject(marshal, reserved);
2164 IMarshal_Release(marshal);
2165 return hr;
2166 }
2167
2169 {
2170 ERR("apartment not initialised\n");
2171 return CO_E_NOTINITIALIZED;
2172 }
2173
2174 manager = get_stub_manager_from_object(apt, lpUnk, FALSE);
2175 if (manager) {
2176 stub_manager_disconnect(manager);
2177 /* Release stub manager twice, to remove the apartment reference. */
2178 stub_manager_int_release(manager);
2179 stub_manager_int_release(manager);
2180 }
2181
2182 /* Note: native is pretty broken here because it just silently
2183 * fails, without returning an appropriate error code if the object was
2184 * not found, making apps think that the object was disconnected, when
2185 * it actually wasn't */
2186
2188 return S_OK;
2189}
2190
2191/******************************************************************************
2192 * CoCreateGuid [OLE32.@]
2193 *
2194 * Simply forwards to UuidCreate in RPCRT4.
2195 *
2196 * PARAMS
2197 * pguid [O] Points to the GUID to initialize.
2198 *
2199 * RETURNS
2200 * Success: S_OK.
2201 * Failure: HRESULT code.
2202 *
2203 * SEE ALSO
2204 * UuidCreate
2205 */
2207{
2208 DWORD status;
2209
2210 if(!pguid) return E_INVALIDARG;
2211
2212 status = UuidCreate(pguid);
2213 if (status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY) return S_OK;
2214 return HRESULT_FROM_WIN32( status );
2215}
2216
2217static inline BOOL is_valid_hex(WCHAR c)
2218{
2219 if (!(((c >= '0') && (c <= '9')) ||
2220 ((c >= 'a') && (c <= 'f')) ||
2221 ((c >= 'A') && (c <= 'F'))))
2222 return FALSE;
2223 return TRUE;
2224}
2225
2226static const BYTE guid_conv_table[256] =
2227{
2228 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
2229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
2230 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
2231 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
2232 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
2233 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
2234 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
2235};
2236
2237/* conversion helper for CLSIDFromString/IIDFromString */
2239{
2240 int i;
2241
2242 if (!s || s[0]!='{') {
2243 memset( id, 0, sizeof (CLSID) );
2244 if(!s) return TRUE;
2245 return FALSE;
2246 }
2247
2248 TRACE("%s -> %p\n", debugstr_w(s), id);
2249
2250 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
2251
2252 id->Data1 = 0;
2253 for (i = 1; i < 9; i++) {
2254 if (!is_valid_hex(s[i])) return FALSE;
2255 id->Data1 = (id->Data1 << 4) | guid_conv_table[s[i]];
2256 }
2257 if (s[9]!='-') return FALSE;
2258
2259 id->Data2 = 0;
2260 for (i = 10; i < 14; i++) {
2261 if (!is_valid_hex(s[i])) return FALSE;
2262 id->Data2 = (id->Data2 << 4) | guid_conv_table[s[i]];
2263 }
2264 if (s[14]!='-') return FALSE;
2265
2266 id->Data3 = 0;
2267 for (i = 15; i < 19; i++) {
2268 if (!is_valid_hex(s[i])) return FALSE;
2269 id->Data3 = (id->Data3 << 4) | guid_conv_table[s[i]];
2270 }
2271 if (s[19]!='-') return FALSE;
2272
2273 for (i = 20; i < 37; i+=2) {
2274 if (i == 24) {
2275 if (s[i]!='-') return FALSE;
2276 i++;
2277 }
2278 if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return FALSE;
2279 id->Data4[(i-20)/2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i+1]];
2280 }
2281
2282 if (s[37] == '}' && s[38] == '\0')
2283 return TRUE;
2284
2285 return FALSE;
2286}
2287
2288/*****************************************************************************/
2289
2291{
2292 static const WCHAR clsidW[] = { '\\','C','L','S','I','D',0 };
2293 WCHAR buf2[CHARS_IN_GUID];
2294 LONG buf2len = sizeof(buf2);
2295 HKEY xhkey;
2296 WCHAR *buf;
2297
2298 memset(clsid, 0, sizeof(*clsid));
2299 buf = HeapAlloc( GetProcessHeap(),0,(lstrlenW(progid)+8) * sizeof(WCHAR) );
2300 if (!buf) return E_OUTOFMEMORY;
2301 lstrcpyW( buf, progid );
2302 lstrcatW( buf, clsidW );
2304 {
2306 WARN("couldn't open key for ProgID %s\n", debugstr_w(progid));
2307 return CO_E_CLASSSTRING;
2308 }
2310
2311 if (RegQueryValueW(xhkey,NULL,buf2,&buf2len))
2312 {
2313 RegCloseKey(xhkey);
2314 WARN("couldn't query clsid value for ProgID %s\n", debugstr_w(progid));
2315 return CO_E_CLASSSTRING;
2316 }
2317 RegCloseKey(xhkey);
2318 return guid_from_string(buf2, clsid) ? S_OK : CO_E_CLASSSTRING;
2319}
2320
2321/******************************************************************************
2322 * CLSIDFromString [OLE32.@]
2323 *
2324 * Converts a unique identifier from its string representation into
2325 * the GUID struct.
2326 *
2327 * PARAMS
2328 * idstr [I] The string representation of the GUID.
2329 * id [O] GUID converted from the string.
2330 *
2331 * RETURNS
2332 * S_OK on success
2333 * CO_E_CLASSSTRING if idstr is not a valid CLSID
2334 *
2335 * SEE ALSO
2336 * StringFromCLSID
2337 */
2339{
2341 CLSID tmp_id;
2342
2343 if (!id)
2344 return E_INVALIDARG;
2345
2346 if (guid_from_string(idstr, id))
2347 return S_OK;
2348
2349 /* It appears a ProgID is also valid */
2350 ret = clsid_from_string_reg(idstr, &tmp_id);
2351 if(SUCCEEDED(ret))
2352 *id = tmp_id;
2353
2354 return ret;
2355}
2356
2357/******************************************************************************
2358 * IIDFromString [OLE32.@]
2359 *
2360 * Converts an interface identifier from its string representation to
2361 * the IID struct.
2362 *
2363 * PARAMS
2364 * idstr [I] The string representation of the GUID.
2365 * id [O] IID converted from the string.
2366 *
2367 * RETURNS
2368 * S_OK on success
2369 * CO_E_IIDSTRING if idstr is not a valid IID
2370 *
2371 * SEE ALSO
2372 * StringFromIID
2373 */
2375{
2376 TRACE("%s -> %p\n", debugstr_w(s), iid);
2377
2378 if (!s)
2379 {
2380 memset(iid, 0, sizeof(*iid));
2381 return S_OK;
2382 }
2383
2384 /* length mismatch is a special case */
2385 if (lstrlenW(s) + 1 != CHARS_IN_GUID)
2386 return E_INVALIDARG;
2387
2388 if (s[0] != '{')
2389 return CO_E_IIDSTRING;
2390
2391 return guid_from_string(s, iid) ? S_OK : CO_E_IIDSTRING;
2392}
2393
2394/******************************************************************************
2395 * StringFromCLSID [OLE32.@]
2396 * StringFromIID [OLE32.@]
2397 *
2398 * Converts a GUID into the respective string representation.
2399 * The target string is allocated using the OLE IMalloc.
2400 *
2401 * PARAMS
2402 * id [I] the GUID to be converted.
2403 * idstr [O] A pointer to a to-be-allocated pointer pointing to the resulting string.
2404 *
2405 * RETURNS
2406 * S_OK
2407 * E_FAIL
2408 *
2409 * SEE ALSO
2410 * StringFromGUID2, CLSIDFromString
2411 */
2413{
2414 if (!(*idstr = CoTaskMemAlloc(CHARS_IN_GUID * sizeof(WCHAR)))) return E_OUTOFMEMORY;
2415 StringFromGUID2( id, *idstr, CHARS_IN_GUID );
2416 return S_OK;
2417}
2418
2419/******************************************************************************
2420 * StringFromGUID2 [OLE32.@]
2421 *
2422 * Modified version of StringFromCLSID that allows you to specify max
2423 * buffer size.
2424 *
2425 * PARAMS
2426 * id [I] GUID to convert to string.
2427 * str [O] Buffer where the result will be stored.
2428 * cmax [I] Size of the buffer in characters.
2429 *
2430 * RETURNS
2431 * Success: The length of the resulting string in characters.
2432 * Failure: 0.
2433 */
2435{
2436 static const WCHAR formatW[] = { '{','%','0','8','X','-','%','0','4','X','-',
2437 '%','0','4','X','-','%','0','2','X','%','0','2','X','-',
2438 '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X',
2439 '%','0','2','X','%','0','2','X','}',0 };
2440 if (!id || cmax < CHARS_IN_GUID) return 0;
2441 swprintf( str, formatW, id->Data1, id->Data2, id->Data3,
2442 id->Data4[0], id->Data4[1], id->Data4[2], id->Data4[3],
2443 id->Data4[4], id->Data4[5], id->Data4[6], id->Data4[7] );
2444 return CHARS_IN_GUID;
2445}
2446
2447/* open HKCR\\CLSID\\{string form of clsid}\\{keyname} key */
2449{
2450 static const WCHAR wszCLSIDSlash[] = {'C','L','S','I','D','\\',0};
2451 WCHAR path[CHARS_IN_GUID + ARRAY_SIZE(wszCLSIDSlash) - 1];
2452 LONG res;
2453 HKEY key;
2454
2455 lstrcpyW(path, wszCLSIDSlash);
2456 StringFromGUID2(clsid, path + lstrlenW(wszCLSIDSlash), CHARS_IN_GUID);
2459 return REGDB_E_CLASSNOTREG;
2460 else if (res != ERROR_SUCCESS)
2461 return REGDB_E_READREGDB;
2462
2463 if (!keyname)
2464 {
2465 *subkey = key;
2466 return S_OK;
2467 }
2468
2469 res = open_classes_key(key, keyname, access, subkey);
2472 return REGDB_E_KEYMISSING;
2473 else if (res != ERROR_SUCCESS)
2474 return REGDB_E_READREGDB;
2475
2476 return S_OK;
2477}
2478
2479/* open HKCR\\AppId\\{string form of appid clsid} key */
2481{
2482 static const WCHAR szAppId[] = { 'A','p','p','I','d',0 };
2483 static const WCHAR szAppIdKey[] = { 'A','p','p','I','d','\\',0 };
2484 DWORD res;
2486 WCHAR keyname[ARRAY_SIZE(szAppIdKey) + CHARS_IN_GUID];
2487 DWORD size;
2488 HKEY hkey;
2489 DWORD type;
2490 HRESULT hr;
2491
2492 /* read the AppID value under the class's key */
2494 if (FAILED(hr))
2495 return hr;
2496
2497 size = sizeof(buf);
2498 res = RegQueryValueExW(hkey, szAppId, NULL, &type, (LPBYTE)buf, &size);
2499 RegCloseKey(hkey);
2501 return REGDB_E_KEYMISSING;
2502 else if (res != ERROR_SUCCESS || type!=REG_SZ)
2503 return REGDB_E_READREGDB;
2504
2505 lstrcpyW(keyname, szAppIdKey);
2506 lstrcatW(keyname, buf);
2507 res = open_classes_key(HKEY_CLASSES_ROOT, keyname, access, subkey);
2509 return REGDB_E_KEYMISSING;
2510 else if (res != ERROR_SUCCESS)
2511 return REGDB_E_READREGDB;
2512
2513 return S_OK;
2514}
2515
2516/******************************************************************************
2517 * ProgIDFromCLSID [OLE32.@]
2518 *
2519 * Converts a class id into the respective program ID.
2520 *
2521 * PARAMS
2522 * clsid [I] Class ID, as found in registry.
2523 * ppszProgID [O] Associated ProgID.
2524 *
2525 * RETURNS
2526 * S_OK
2527 * E_OUTOFMEMORY
2528 * REGDB_E_CLASSNOTREG if the given clsid has no associated ProgID
2529 */
2531{
2532 static const WCHAR wszProgID[] = {'P','r','o','g','I','D',0};
2533 ACTCTX_SECTION_KEYED_DATA data;
2534 HKEY hkey;
2535 HRESULT ret;
2536 LONG progidlen = 0;
2537
2538 if (!ppszProgID)
2539 return E_INVALIDARG;
2540
2541 *ppszProgID = NULL;
2542
2543 data.cbSize = sizeof(data);
2544 if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,
2545 clsid, &data))
2546 {
2547 struct comclassredirect_data *comclass = (struct comclassredirect_data*)data.lpData;
2548 if (comclass->progid_len)
2549 {
2550 WCHAR *ptrW;
2551
2552 *ppszProgID = CoTaskMemAlloc(comclass->progid_len + sizeof(WCHAR));
2553 if (!*ppszProgID) return E_OUTOFMEMORY;
2554
2555 ptrW = (WCHAR*)((BYTE*)comclass + comclass->progid_offset);
2556 memcpy(*ppszProgID, ptrW, comclass->progid_len + sizeof(WCHAR));
2557 return S_OK;
2558 }
2559 else
2560 return REGDB_E_CLASSNOTREG;
2561 }
2562
2563 ret = COM_OpenKeyForCLSID(clsid, wszProgID, KEY_READ, &hkey);
2564 if (FAILED(ret))
2565 return ret;
2566
2567 if (RegQueryValueW(hkey, NULL, NULL, &progidlen))
2569
2570 if (ret == S_OK)
2571 {
2572 *ppszProgID = CoTaskMemAlloc(progidlen * sizeof(WCHAR));
2573 if (*ppszProgID)
2574 {
2575 if (RegQueryValueW(hkey, NULL, *ppszProgID, &progidlen)) {
2577 CoTaskMemFree(*ppszProgID);
2578 *ppszProgID = NULL;
2579 }
2580 }
2581 else
2583 }
2584
2585 RegCloseKey(hkey);
2586 return ret;
2587}
2588
2589/******************************************************************************
2590 * CLSIDFromProgID [OLE32.@]
2591 *
2592 * Converts a program id into the respective GUID.
2593 *
2594 * PARAMS
2595 * progid [I] Unicode program ID, as found in registry.
2596 * clsid [O] Associated CLSID.
2597 *
2598 * RETURNS
2599 * Success: S_OK
2600 * Failure: CO_E_CLASSSTRING - the given ProgID cannot be found.
2601 */
2603{
2604 ACTCTX_SECTION_KEYED_DATA data;
2605
2606 if (!progid || !clsid)
2607 return E_INVALIDARG;
2608
2609 data.cbSize = sizeof(data);
2610 if (FindActCtxSectionStringW(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION,
2611 progid, &data))
2612 {
2613 struct progidredirect_data *progiddata = (struct progidredirect_data*)data.lpData;
2614 CLSID *alias = (CLSID*)((BYTE*)data.lpSectionBase + progiddata->clsid_offset);
2615 *clsid = *alias;
2616 return S_OK;
2617 }
2618
2620}
2621
2622/******************************************************************************
2623 * CLSIDFromProgIDEx [OLE32.@]
2624 */
2626{
2627 FIXME("%s,%p: semi-stub\n", debugstr_w(progid), clsid);
2628
2629 return CLSIDFromProgID(progid, clsid);
2630}
2631
2633{
2634 HKEY hkey;
2636 DWORD len;
2637
2638 access |= KEY_READ;
2639
2641 return REGDB_E_IIDNOTREG;
2642
2643 len = sizeof(value);
2644 if (ERROR_SUCCESS != RegQueryValueExW(hkey, NULL, NULL, NULL, (BYTE *)value, &len))
2645 return REGDB_E_IIDNOTREG;
2646 RegCloseKey(hkey);
2647
2648 if (CLSIDFromString(value, pclsid) != NOERROR)
2649 return REGDB_E_IIDNOTREG;
2650
2651 return S_OK;
2652}
2653
2654/*****************************************************************************
2655 * CoGetPSClsid [OLE32.@]
2656 *
2657 * Retrieves the CLSID of the proxy/stub factory that implements
2658 * IPSFactoryBuffer for the specified interface.
2659 *
2660 * PARAMS
2661 * riid [I] Interface whose proxy/stub CLSID is to be returned.
2662 * pclsid [O] Where to store returned proxy/stub CLSID.
2663 *
2664 * RETURNS
2665 * S_OK
2666 * E_OUTOFMEMORY
2667 * REGDB_E_IIDNOTREG if no PSFactoryBuffer is associated with the IID, or it could not be parsed
2668 *
2669 * NOTES
2670 *
2671 * The standard marshaller activates the object with the CLSID
2672 * returned and uses the CreateProxy and CreateStub methods on its
2673 * IPSFactoryBuffer interface to construct the proxies and stubs for a
2674 * given object.
2675 *
2676 * CoGetPSClsid determines this CLSID by searching the
2677 * HKEY_CLASSES_ROOT\Interface\{string form of riid}\ProxyStubClsid32
2678 * in the registry and any interface id registered by
2679 * CoRegisterPSClsid within the current process.
2680 *
2681 * BUGS
2682 *
2683 * Native returns S_OK for interfaces with a key in HKCR\Interface, but
2684 * without a ProxyStubClsid32 key and leaves garbage in pclsid. This should be
2685 * considered a bug in native unless an application depends on this (unlikely).
2686 *
2687 * SEE ALSO
2688 * CoRegisterPSClsid.
2689 */
2691{
2692 static const WCHAR wszInterface[] = {'I','n','t','e','r','f','a','c','e','\\',0};
2693 static const WCHAR wszPSC[] = {'\\','P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
2694 WCHAR path[ARRAY_SIZE(wszInterface) - 1 + CHARS_IN_GUID - 1 + ARRAY_SIZE(wszPSC)];
2695 APARTMENT *apt;
2697 ACTCTX_SECTION_KEYED_DATA data;
2698 HRESULT hr;
2699 REGSAM opposite = (sizeof(void*) > sizeof(int)) ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
2700 BOOL is_wow64;
2701
2702 TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid), pclsid);
2703
2704 if (!(apt = apartment_get_current_or_mta()))
2705 {
2706 ERR("apartment not initialised\n");
2707 return CO_E_NOTINITIALIZED;
2708 }
2709 apartment_release(apt);
2710
2711 if (!pclsid)
2712 return E_INVALIDARG;
2713
2715
2718 {
2719 *pclsid = registered_psclsid->clsid;
2721 return S_OK;
2722 }
2723
2725
2726 data.cbSize = sizeof(data);
2727 if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION,
2728 riid, &data))
2729 {
2730 struct ifacepsredirect_data *ifaceps = (struct ifacepsredirect_data*)data.lpData;
2731 *pclsid = ifaceps->iid;
2732 return S_OK;
2733 }
2734
2735 /* Interface\\{string form of riid}\\ProxyStubClsid32 */
2736 lstrcpyW(path, wszInterface);
2737 StringFromGUID2(riid, path + ARRAY_SIZE(wszInterface) - 1, CHARS_IN_GUID);
2738 lstrcpyW(path + ARRAY_SIZE(wszInterface) - 1 + CHARS_IN_GUID - 1, wszPSC);
2739
2740 hr = get_ps_clsid_from_registry(path, 0, pclsid);
2741 if (FAILED(hr) && (opposite == KEY_WOW64_32KEY ||
2743 hr = get_ps_clsid_from_registry(path, opposite, pclsid);
2744
2745 if (hr == S_OK)
2746 TRACE ("() Returning CLSID=%s\n", debugstr_guid(pclsid));
2747 else
2748 WARN("No PSFactoryBuffer object is registered for IID %s\n", debugstr_guid(riid));
2749
2750 return hr;
2751}
2752
2753/*****************************************************************************
2754 * CoRegisterPSClsid [OLE32.@]
2755 *
2756 * Register a proxy/stub CLSID for the given interface in the current process
2757 * only.
2758 *
2759 * PARAMS
2760 * riid [I] Interface whose proxy/stub CLSID is to be registered.
2761 * rclsid [I] CLSID of the proxy/stub.
2762 *
2763 * RETURNS
2764 * Success: S_OK
2765 * Failure: E_OUTOFMEMORY
2766 *
2767 * NOTES
2768 *
2769 * Unlike CoRegisterClassObject(), CLSIDs registered with CoRegisterPSClsid()
2770 * will be returned from other apartments in the same process.
2771 *
2772 * This function does not add anything to the registry and the effects are
2773 * limited to the lifetime of the current process.
2774 *
2775 * SEE ALSO
2776 * CoGetPSClsid.
2777 */
2779{
2780 APARTMENT *apt;
2782
2783 TRACE("(%s, %s)\n", debugstr_guid(riid), debugstr_guid(rclsid));
2784
2785 if (!(apt = apartment_get_current_or_mta()))
2786 {
2787 ERR("apartment not initialised\n");
2788 return CO_E_NOTINITIALIZED;
2789 }
2790 apartment_release(apt);
2791
2793
2796 {
2797 registered_psclsid->clsid = *rclsid;
2799 return S_OK;
2800 }
2801
2803 if (!registered_psclsid)
2804 {
2806 return E_OUTOFMEMORY;
2807 }
2808
2810 registered_psclsid->clsid = *rclsid;
2812
2814
2815 return S_OK;
2816}
2817
2818
2819/***
2820 * COM_GetRegisteredClassObject
2821 *
2822 * This internal method is used to scan the registered class list to
2823 * find a class object.
2824 *
2825 * Params:
2826 * rclsid Class ID of the class to find.
2827 * dwClsContext Class context to match.
2828 * ppv [out] returns a pointer to the class object. Complying
2829 * to normal COM usage, this method will increase the
2830 * reference count on this object.
2831 */
2833 DWORD dwClsContext, LPUNKNOWN* ppUnk)
2834{
2835 HRESULT hr = S_FALSE;
2836 RegisteredClass *curClass;
2837
2839
2841 {
2842 /*
2843 * Check if we have a match on the class ID and context.
2844 */
2845 if ((apt->oxid == curClass->apartment_id) &&
2846 (dwClsContext & curClass->runContext) &&
2847 IsEqualGUID(&(curClass->classIdentifier), rclsid))
2848 {
2849 /*
2850 * We have a match, return the pointer to the class object.
2851 */
2852 *ppUnk = curClass->classObject;
2853
2854 IUnknown_AddRef(curClass->classObject);
2855
2856 hr = S_OK;
2857 break;
2858 }
2859 }
2860
2862
2863 return hr;
2864}
2865
2866/******************************************************************************
2867 * CoRegisterClassObject [OLE32.@]
2868 *
2869 * Registers the class object for a given class ID. Servers housed in EXE
2870 * files use this method instead of exporting DllGetClassObject to allow
2871 * other code to connect to their objects.
2872 *
2873 * PARAMS
2874 * rclsid [I] CLSID of the object to register.
2875 * pUnk [I] IUnknown of the object.
2876 * dwClsContext [I] CLSCTX flags indicating the context in which to run the executable.
2877 * flags [I] REGCLS flags indicating how connections are made.
2878 * lpdwRegister [I] A unique cookie that can be passed to CoRevokeClassObject.
2879 *
2880 * RETURNS
2881 * S_OK on success,
2882 * E_INVALIDARG if lpdwRegister or pUnk are NULL,
2883 * CO_E_OBJISREG if the object is already registered. We should not return this.
2884 *
2885 * SEE ALSO
2886 * CoRevokeClassObject, CoGetClassObject
2887 *
2888 * NOTES
2889 * In-process objects are only registered for the current apartment.
2890 * CoGetClassObject() and CoCreateInstance() will not return objects registered
2891 * in other apartments.
2892 *
2893 * BUGS
2894 * MSDN claims that multiple interface registrations are legal, but we
2895 * can't do that with our current implementation.
2896 */
2898 REFCLSID rclsid,
2900 DWORD dwClsContext,
2901 DWORD flags,
2902 LPDWORD lpdwRegister)
2903{
2904 static LONG next_cookie;
2905 RegisteredClass* newClass;
2906 LPUNKNOWN foundObject;
2907 HRESULT hr;
2908 APARTMENT *apt;
2909
2910 TRACE("(%s,%p,0x%08x,0x%08x,%p)\n",
2911 debugstr_guid(rclsid),pUnk,dwClsContext,flags,lpdwRegister);
2912
2913 if ( (lpdwRegister==0) || (pUnk==0) )
2914 return E_INVALIDARG;
2915
2916 if (!(apt = apartment_get_current_or_mta()))
2917 {
2918 ERR("COM was not initialized\n");
2919 return CO_E_NOTINITIALIZED;
2920 }
2921
2922 *lpdwRegister = 0;
2923
2924 /* REGCLS_MULTIPLEUSE implies registering as inproc server. This is what
2925 * differentiates the flag from REGCLS_MULTI_SEPARATE. */
2927 dwClsContext |= CLSCTX_INPROC_SERVER;
2928
2929 /*
2930 * First, check if the class is already registered.
2931 * If it is, this should cause an error.
2932 */
2933 hr = COM_GetRegisteredClassObject(apt, rclsid, dwClsContext, &foundObject);
2934 if (hr == S_OK) {
2935 if (flags & REGCLS_MULTIPLEUSE) {
2936 if (dwClsContext & CLSCTX_LOCAL_SERVER)
2937 hr = CoLockObjectExternal(foundObject, TRUE, FALSE);
2938 IUnknown_Release(foundObject);
2939 apartment_release(apt);
2940 return hr;
2941 }
2942 IUnknown_Release(foundObject);
2943 ERR("object already registered for class %s\n", debugstr_guid(rclsid));
2944 apartment_release(apt);
2945 return CO_E_OBJISREG;
2946 }
2947
2948 newClass = HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass));
2949 if ( newClass == NULL )
2950 {
2951 apartment_release(apt);
2952 return E_OUTOFMEMORY;
2953 }
2954
2955 newClass->classIdentifier = *rclsid;
2956 newClass->apartment_id = apt->oxid;
2957 newClass->runContext = dwClsContext;
2958 newClass->connectFlags = flags;
2959 newClass->RpcRegistration = NULL;
2960
2961 if (!(newClass->dwCookie = InterlockedIncrement( &next_cookie )))
2962 newClass->dwCookie = InterlockedIncrement( &next_cookie );
2963
2964 /*
2965 * Since we're making a copy of the object pointer, we have to increase its
2966 * reference count.
2967 */
2968 newClass->classObject = pUnk;
2969 IUnknown_AddRef(newClass->classObject);
2970
2974
2975 *lpdwRegister = newClass->dwCookie;
2976
2977 if (dwClsContext & CLSCTX_LOCAL_SERVER) {
2978 IStream *marshal_stream;
2979
2980 hr = get_local_server_stream(apt, &marshal_stream);
2981 if(FAILED(hr))
2982 {
2983 apartment_release(apt);
2984 return hr;
2985 }
2986
2988 marshal_stream,
2990 &newClass->RpcRegistration);
2991 IStream_Release(marshal_stream);
2992 }
2993 apartment_release(apt);
2994 return S_OK;
2995}
2996
2998{
2999 if (data->hkey)
3000 {
3001 static const WCHAR wszThreadingModel[] = {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
3002 static const WCHAR wszApartment[] = {'A','p','a','r','t','m','e','n','t',0};
3003 static const WCHAR wszFree[] = {'F','r','e','e',0};
3004 static const WCHAR wszBoth[] = {'B','o','t','h',0};
3005 WCHAR threading_model[10 /* lstrlenW(L"apartment")+1 */];
3006 DWORD dwLength = sizeof(threading_model);
3007 DWORD keytype;
3008 DWORD ret;
3009
3010 ret = RegQueryValueExW(data->u.hkey, wszThreadingModel, NULL, &keytype, (BYTE*)threading_model, &dwLength);
3011 if ((ret != ERROR_SUCCESS) || (keytype != REG_SZ))
3012 threading_model[0] = '\0';
3013
3014 if (!wcsicmp(threading_model, wszApartment)) return ThreadingModel_Apartment;
3015 if (!wcsicmp(threading_model, wszFree)) return ThreadingModel_Free;
3016 if (!wcsicmp(threading_model, wszBoth)) return ThreadingModel_Both;
3017
3018 /* there's not specific handling for this case */
3019 if (threading_model[0]) return ThreadingModel_Neutral;
3020 return ThreadingModel_No;
3021 }
3022 else
3023 return data->u.actctx.data->model;
3024}
3025
3026static HRESULT get_inproc_class_object(APARTMENT *apt, const struct class_reg_data *regdata,
3027 REFCLSID rclsid, REFIID riid,
3028 BOOL hostifnecessary, void **ppv)
3029{
3031 BOOL apartment_threaded;
3032
3033 if (hostifnecessary)
3034 {
3035 enum comclass_threadingmodel model = get_threading_model(regdata);
3036
3037 if (model == ThreadingModel_Apartment)
3038 {
3039 apartment_threaded = TRUE;
3040 if (apt->multi_threaded)
3041 return apartment_hostobject_in_hostapt(apt, FALSE, FALSE, regdata, rclsid, riid, ppv);
3042 }
3043 else if (model == ThreadingModel_Free)
3044 {
3045 apartment_threaded = FALSE;
3046 if (!apt->multi_threaded)
3047 return apartment_hostobject_in_hostapt(apt, TRUE, FALSE, regdata, rclsid, riid, ppv);
3048 }
3049 /* everything except "Apartment", "Free" and "Both" */
3050 else if (model != ThreadingModel_Both)
3051 {
3052 apartment_threaded = TRUE;
3053 /* everything else is main-threaded */
3054 if (model != ThreadingModel_No)
3055 FIXME("unrecognised threading model %d for object %s, should be main-threaded?\n", model, debugstr_guid(rclsid));
3056
3057 if (apt->multi_threaded || !apt->main)
3058 return apartment_hostobject_in_hostapt(apt, FALSE, TRUE, regdata, rclsid, riid, ppv);
3059 }
3060 else
3061 apartment_threaded = FALSE;
3062 }
3063 else
3064 apartment_threaded = !apt->multi_threaded;
3065
3067 {
3068 /* failure: CLSID is not found in registry */
3069 WARN("class %s not registered inproc\n", debugstr_guid(rclsid));
3070 return REGDB_E_CLASSNOTREG;
3071 }
3072
3073 return apartment_getclassobject(apt, dllpath, apartment_threaded,
3074 rclsid, riid, ppv);
3075}
3076
3077/***********************************************************************
3078 * CoGetClassObject [OLE32.@]
3079 *
3080 * Creates an object of the specified class.
3081 *
3082 * PARAMS
3083 * rclsid [I] Class ID to create an instance of.
3084 * dwClsContext [I] Flags to restrict the location of the created instance.
3085 * pServerInfo [I] Optional. Details for connecting to a remote server.
3086 * iid [I] The ID of the interface of the instance to return.
3087 * ppv [O] On returns, contains a pointer to the specified interface of the object.
3088 *
3089 * RETURNS
3090 * Success: S_OK
3091 * Failure: HRESULT code.
3092 *
3093 * NOTES
3094 * The dwClsContext parameter can be one or more of the following:
3095 *| CLSCTX_INPROC_SERVER - Use an in-process server, such as from a DLL.
3096 *| CLSCTX_INPROC_HANDLER - Use an in-process object which handles certain functions for an object running in another process.
3097 *| CLSCTX_LOCAL_SERVER - Connect to an object running in another process.
3098 *| CLSCTX_REMOTE_SERVER - Connect to an object running on another machine.
3099 *
3100 * SEE ALSO
3101 * CoCreateInstance()
3102 */
3104 REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo,
3105 REFIID iid, LPVOID *ppv)
3106{
3107 struct class_reg_data clsreg;
3108 IUnknown *regClassObject;
3110 APARTMENT *apt;
3111
3112 TRACE("CLSID: %s,IID: %s\n", debugstr_guid(rclsid), debugstr_guid(iid));
3113
3114 if (!ppv)
3115 return E_INVALIDARG;
3116
3117 *ppv = NULL;
3118
3119 if (!(apt = apartment_get_current_or_mta()))
3120 {
3121 ERR("apartment not initialised\n");
3122 return CO_E_NOTINITIALIZED;
3123 }
3124
3125 if (pServerInfo) {
3126 FIXME("pServerInfo->name=%s pAuthInfo=%p\n",
3127 debugstr_w(pServerInfo->pwszName), pServerInfo->pAuthInfo);
3128 }
3129
3130 if (CLSCTX_INPROC_SERVER & dwClsContext)
3131 {
3133 {
3134 apartment_release(apt);
3135 return FTMarshalCF_Create(iid, ppv);
3136 }
3137 if (IsEqualCLSID(rclsid, &CLSID_GlobalOptions))
3138 return IClassFactory_QueryInterface(&GlobalOptionsCF, iid, ppv);
3139 }
3140
3141 if (CLSCTX_INPROC & dwClsContext)
3142 {
3143 ACTCTX_SECTION_KEYED_DATA data;
3144
3145 data.cbSize = sizeof(data);
3146 /* search activation context first */
3147 if (FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
3148 ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,
3149 rclsid, &data))
3150 {
3151 struct comclassredirect_data *comclass = (struct comclassredirect_data*)data.lpData;
3152
3153 clsreg.u.actctx.hactctx = data.hActCtx;
3154 clsreg.u.actctx.data = data.lpData;
3155 clsreg.u.actctx.section = data.lpSectionBase;
3156 clsreg.hkey = FALSE;
3157
3158 hres = get_inproc_class_object(apt, &clsreg, &comclass->clsid, iid, !(dwClsContext & WINE_CLSCTX_DONT_HOST), ppv);
3159 ReleaseActCtx(data.hActCtx);
3160 apartment_release(apt);
3161 return hres;
3162 }
3163 }
3164
3165 /*
3166 * First, try and see if we can't match the class ID with one of the
3167 * registered classes.
3168 */
3169 if (S_OK == COM_GetRegisteredClassObject(apt, rclsid, dwClsContext,
3170 &regClassObject))
3171 {
3172 /* Get the required interface from the retrieved pointer. */
3173 hres = IUnknown_QueryInterface(regClassObject, iid, ppv);
3174
3175 /*
3176 * Since QI got another reference on the pointer, we want to release the
3177 * one we already have. If QI was unsuccessful, this will release the object. This
3178 * is good since we are not returning it in the "out" parameter.
3179 */
3180 IUnknown_Release(regClassObject);
3181 apartment_release(apt);
3182 return hres;
3183 }
3184
3185 /* First try in-process server */
3186 if (CLSCTX_INPROC_SERVER & dwClsContext)
3187 {
3188 static const WCHAR wszInprocServer32[] = {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
3189 HKEY hkey;
3190
3191 hres = COM_OpenKeyForCLSID(rclsid, wszInprocServer32, KEY_READ, &hkey);
3192 if (FAILED(hres))
3193 {
3195 ERR("class %s not registered\n", debugstr_guid(rclsid));
3196 else if (hres == REGDB_E_KEYMISSING)
3197 {
3198 WARN("class %s not registered as in-proc server\n", debugstr_guid(rclsid));
3200 }
3201 }
3202
3203 if (SUCCEEDED(hres))
3204 {
3205 clsreg.u.hkey = hkey;
3206 clsreg.hkey = TRUE;
3207
3208 hres = get_inproc_class_object(apt, &clsreg, rclsid, iid, !(dwClsContext & WINE_CLSCTX_DONT_HOST), ppv);
3209 RegCloseKey(hkey);
3210 }
3211
3212 /* return if we got a class, otherwise fall through to one of the
3213 * other types */
3214 if (SUCCEEDED(hres))
3215 {
3216 apartment_release(apt);
3217 return hres;
3218 }
3219 }
3220
3221 /* Next try in-process handler */
3222 if (CLSCTX_INPROC_HANDLER & dwClsContext)
3223 {
3224 static const WCHAR wszInprocHandler32[] = {'I','n','p','r','o','c','H','a','n','d','l','e','r','3','2',0};
3225 HKEY hkey;
3226
3227 hres = COM_OpenKeyForCLSID(rclsid, wszInprocHandler32, KEY_READ, &hkey);
3228 if (FAILED(hres))
3229 {
3231 ERR("class %s not registered\n", debugstr_guid(rclsid));
3232 else if (hres == REGDB_E_KEYMISSING)
3233 {
3234 WARN("class %s not registered in-proc handler\n", debugstr_guid(rclsid));
3236 }
3237 }
3238
3239 if (SUCCEEDED(hres))
3240 {
3241 clsreg.u.hkey = hkey;
3242 clsreg.hkey = TRUE;
3243
3244 hres = get_inproc_class_object(apt, &clsreg, rclsid, iid, !(dwClsContext & WINE_CLSCTX_DONT_HOST), ppv);
3245 RegCloseKey(hkey);
3246 }
3247
3248 /* return if we got a class, otherwise fall through to one of the
3249 * other types */
3250 if (SUCCEEDED(hres))
3251 {
3252 apartment_release(apt);
3253 return hres;
3254 }
3255 }
3256 apartment_release(apt);
3257
3258 /* Next try out of process */
3259 if (CLSCTX_LOCAL_SERVER & dwClsContext)
3260 {
3261 hres = RPC_GetLocalClassObject(rclsid,iid,ppv);
3262 if (SUCCEEDED(hres))
3263 return hres;
3264 }
3265
3266 /* Finally try remote: this requires networked DCOM (a lot of work) */
3267 if (CLSCTX_REMOTE_SERVER & dwClsContext)
3268 {
3269 FIXME ("CLSCTX_REMOTE_SERVER not supported\n");
3271 }
3272
3273 if (FAILED(hres))
3274 ERR("no class object %s could be created for context 0x%x\n",
3275 debugstr_guid(rclsid), dwClsContext);
3276 return hres;
3277}
3278
3279/***********************************************************************
3280 * CoResumeClassObjects (OLE32.@)
3281 *
3282 * Resumes all class objects registered with REGCLS_SUSPENDED.
3283 *
3284 * RETURNS
3285 * Success: S_OK.
3286 * Failure: HRESULT code.
3287 */
3289{
3290 FIXME("stub\n");
3291 return S_OK;
3292}
3293
3294/***********************************************************************
3295 * CoCreateInstance [OLE32.@]
3296 *
3297 * Creates an instance of the specified class.
3298 *
3299 * PARAMS
3300 * rclsid [I] Class ID to create an instance of.
3301 * pUnkOuter [I] Optional outer unknown to allow aggregation with another object.
3302 * dwClsContext [I] Flags to restrict the location of the created instance.
3303 * iid [I] The ID of the interface of the instance to return.
3304 * ppv [O] On returns, contains a pointer to the specified interface of the instance.
3305 *
3306 * RETURNS
3307 * Success: S_OK
3308 * Failure: HRESULT code.
3309 *
3310 * NOTES
3311 * The dwClsContext parameter can be one or more of the following:
3312 *| CLSCTX_INPROC_SERVER - Use an in-process server, such as from a DLL.
3313 *| CLSCTX_INPROC_HANDLER - Use an in-process object which handles certain functions for an object running in another process.
3314 *| CLSCTX_LOCAL_SERVER - Connect to an object running in another process.
3315 *| CLSCTX_REMOTE_SERVER - Connect to an object running on another machine.
3316 *
3317 * Aggregation is the concept of deferring the IUnknown of an object to another
3318 * object. This allows a separate object to behave as though it was part of
3319 * the object and to allow this the pUnkOuter parameter can be set. Note that
3320 * not all objects support having an outer of unknown.
3321 *
3322 * SEE ALSO
3323 * CoGetClassObject()
3324 */
3326 REFCLSID rclsid,
3327 LPUNKNOWN pUnkOuter,
3328 DWORD dwClsContext,
3329 REFIID iid,
3330 LPVOID *ppv)
3331{
3332 MULTI_QI multi_qi = { iid };
3333 HRESULT hres;
3334
3335 TRACE("(rclsid=%s, pUnkOuter=%p, dwClsContext=%08x, riid=%s, ppv=%p)\n", debugstr_guid(rclsid),
3336 pUnkOuter, dwClsContext, debugstr_guid(iid), ppv);
3337
3338 if (ppv==0)
3339 return E_POINTER;
3340
3341 hres = CoCreateInstanceEx(rclsid, pUnkOuter, dwClsContext, NULL, 1, &multi_qi);
3342 *ppv = multi_qi.pItf;
3343 return hres;
3344}
3345
3346static void init_multi_qi(DWORD count, MULTI_QI *mqi, HRESULT hr)
3347{
3348 ULONG i;
3349
3350 for (i = 0; i < count; i++)
3351 {
3352 mqi[i].pItf = NULL;
3353 mqi[i].hr = hr;
3354 }
3355}
3356
3357static HRESULT return_multi_qi(IUnknown *unk, DWORD count, MULTI_QI *mqi, BOOL include_unk)
3358{
3359 ULONG index = 0, fetched = 0;
3360
3361 if (include_unk)
3362 {
3363 mqi[0].hr = S_OK;
3364 mqi[0].pItf = unk;
3365 index = fetched = 1;
3366 }
3367
3368 for (; index < count; index++)
3369 {
3370 mqi[index].hr = IUnknown_QueryInterface(unk, mqi[index].pIID, (void**)&mqi[index].pItf);
3371 if (mqi[index].hr == S_OK)
3372 fetched++;
3373 }
3374
3375 if (!include_unk)
3376 IUnknown_Release(unk);
3377
3378 if (fetched == 0)
3379 return E_NOINTERFACE;
3380
3381 return fetched == count ? S_OK : CO_S_NOTALLINTERFACES;
3382}
3383
3384/***********************************************************************
3385 * CoCreateInstanceEx [OLE32.@]
3386 */
3388 REFCLSID rclsid,
3389 LPUNKNOWN pUnkOuter,
3390 DWORD dwClsContext,
3391 COSERVERINFO* pServerInfo,
3392 ULONG cmq,
3393 MULTI_QI* pResults)
3394{
3395 IUnknown *unk = NULL;
3397 APARTMENT *apt;
3398 CLSID clsid;
3399 HRESULT hres;
3400
3401 TRACE("(%s %p %x %p %u %p)\n", debugstr_guid(rclsid), pUnkOuter, dwClsContext, pServerInfo, cmq, pResults);
3402
3403 if (!cmq || !pResults)
3404 return E_INVALIDARG;
3405
3406 if (pServerInfo)
3407 FIXME("() non-NULL pServerInfo not supported!\n");
3408
3409 init_multi_qi(cmq, pResults, E_NOINTERFACE);
3410
3411 hres = CoGetTreatAsClass(rclsid, &clsid);
3412 if(FAILED(hres))
3413 clsid = *rclsid;
3414
3415 if (!(apt = apartment_get_current_or_mta()))
3416 {
3417 ERR("apartment not initialised\n");
3418 return CO_E_NOTINITIALIZED;
3419 }
3420 apartment_release(apt);
3421
3422 /*
3423 * The Standard Global Interface Table (GIT) object is a process-wide singleton.
3424 */
3426 {
3428 TRACE("Retrieving GIT\n");
3429 return return_multi_qi((IUnknown*)git, cmq, pResults, FALSE);
3430 }
3431
3433 hres = ManualResetEvent_Construct(pUnkOuter, pResults[0].pIID, (void**)&unk);
3434 if (FAILED(hres))
3435 return hres;
3436 return return_multi_qi(unk, cmq, pResults, TRUE);
3437 }
3438
3439 /*
3440 * Get a class factory to construct the object we want.
3441 */
3442 hres = CoGetClassObject(&clsid, dwClsContext, NULL, &IID_IClassFactory, (void**)&cf);
3443 if (FAILED(hres))
3444 return hres;
3445
3446 /*
3447 * Create the object and don't forget to release the factory
3448 */
3449 hres = IClassFactory_CreateInstance(cf, pUnkOuter, pResults[0].pIID, (void**)&unk);
3450 IClassFactory_Release(cf);
3451 if (FAILED(hres))
3452 {
3453 if (hres == CLASS_E_NOAGGREGATION && pUnkOuter)
3454 FIXME("Class %s does not support aggregation\n", debugstr_guid(&clsid));
3455 else
3456 FIXME("no instance created for interface %s of class %s, hres is 0x%08x\n",
3457 debugstr_guid(pResults[0].pIID),
3459 return hres;
3460 }
3461
3462 return return_multi_qi(unk, cmq, pResults, TRUE);
3463}
3464
3465/***********************************************************************
3466 * CoGetInstanceFromFile [OLE32.@]
3467 */
3470 CLSID *rclsid,
3471 IUnknown *outer,
3472 DWORD cls_context,
3473 DWORD grfmode,
3475 DWORD count,
3476 MULTI_QI *results
3477)
3478{
3479 IPersistFile *pf = NULL;
3480 IUnknown* unk = NULL;
3481 CLSID clsid;
3482 HRESULT hr;
3483
3484 if (count == 0 || !results)
3485 return E_INVALIDARG;
3486
3487 if (server_info)
3488 FIXME("() non-NULL server_info not supported\n");
3489
3491
3492 /* optionally get CLSID from a file */
3493 if (!rclsid)
3494 {
3496 if (FAILED(hr))
3497 {
3498 ERR("failed to get CLSID from a file\n");
3499 return hr;
3500 }
3501
3502 rclsid = &clsid;
3503 }
3504
3505 hr = CoCreateInstance(rclsid,
3506 outer,
3507 cls_context,
3508 &IID_IUnknown,
3509 (void**)&unk);
3510
3511 if (hr != S_OK)
3512 {
3514 return hr;
3515 }
3516
3517 /* init from file */
3518 hr = IUnknown_QueryInterface(unk, &IID_IPersistFile, (void**)&pf);
3519 if (FAILED(hr))
3520 {
3522 IUnknown_Release(unk);
3523 return hr;
3524 }
3525
3526 hr = IPersistFile_Load(pf, filename, grfmode);
3527 IPersistFile_Release(pf);
3528 if (SUCCEEDED(hr))
3529 return return_multi_qi(unk, count, results, FALSE);
3530 else
3531 {
3533 IUnknown_Release(unk);
3534 return hr;
3535 }
3536}
3537
3538/***********************************************************************
3539 * CoGetInstanceFromIStorage [OLE32.@]
3540 */
3543 CLSID *rclsid,
3544 IUnknown *outer,
3545 DWORD cls_context,
3547 DWORD count,
3548 MULTI_QI *results
3549)
3550{
3551 IPersistStorage *ps = NULL;
3552 IUnknown* unk = NULL;
3553 STATSTG stat;
3554 HRESULT hr;
3555
3556 if (count == 0 || !results || !storage)
3557 return E_INVALIDARG;
3558
3559 if (server_info)
3560 FIXME("() non-NULL server_info not supported\n");
3561
3563
3564 /* optionally get CLSID from a file */
3565 if (!rclsid)
3566 {
3567 memset(&stat.clsid, 0, sizeof(stat.clsid));
3568 hr = IStorage_Stat(storage, &stat, STATFLAG_NONAME);
3569 if (FAILED(hr))
3570 {
3571 ERR("failed to get CLSID from a file\n");
3572 return hr;
3573 }
3574
3575 rclsid = &stat.clsid;
3576 }
3577
3578 hr = CoCreateInstance(rclsid,
3579 outer,
3580 cls_context,
3581 &IID_IUnknown,
3582 (void**)&unk);
3583
3584 if (hr != S_OK)
3585 return hr;
3586
3587 /* init from IStorage */
3588 hr = IUnknown_QueryInterface(unk, &IID_IPersistStorage, (void**)&ps);
3589 if (FAILED(hr))
3590 ERR("failed to get IPersistStorage\n");
3591
3592 if (ps)
3593 {
3594 IPersistStorage_Load(ps, storage);
3595 IPersistStorage_Release(ps);
3596 }
3597
3598 return return_multi_qi(unk, count, results, FALSE);
3599}
3600
3601/***********************************************************************
3602 * CoLoadLibrary (OLE32.@)
3603 *
3604 * Loads a library.
3605 *
3606 * PARAMS
3607 * lpszLibName [I] Path to library.
3608 * bAutoFree [I] Whether the library should automatically be freed.
3609 *
3610 * RETURNS
3611 * Success: Handle to loaded library.
3612 * Failure: NULL.
3613 *
3614 * SEE ALSO
3615 * CoFreeLibrary, CoFreeAllLibraries, CoFreeUnusedLibraries
3616 */
3618{
3619 TRACE("(%s, %d)\n", debugstr_w(lpszLibName), bAutoFree);
3620
3621 return LoadLibraryExW(lpszLibName, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
3622}
3623
3624/***********************************************************************
3625 * CoFreeLibrary [OLE32.@]
3626 *
3627 * Unloads a library from memory.
3628 *
3629 * PARAMS
3630 * hLibrary [I] Handle to library to unload.
3631 *
3632 * RETURNS
3633 * Nothing
3634 *
3635 * SEE ALSO
3636 * CoLoadLibrary, CoFreeAllLibraries, CoFreeUnusedLibraries
3637 */
3639{
3641}
3642
3643
3644/***********************************************************************
3645 * CoFreeAllLibraries [OLE32.@]
3646 *
3647 * Function for backwards compatibility only. Does nothing.
3648 *
3649 * RETURNS
3650 * Nothing.
3651 *
3652 * SEE ALSO
3653 * CoLoadLibrary, CoFreeLibrary, CoFreeUnusedLibraries
3654 */
3656{
3657 /* NOP */
3658}
3659
3660/***********************************************************************
3661 * CoFreeUnusedLibrariesEx [OLE32.@]
3662 *
3663 * Frees any previously unused libraries whose delay has expired and marks
3664 * currently unused libraries for unloading. Unused are identified as those that
3665 * return S_OK from their DllCanUnloadNow function.
3666 *
3667 * PARAMS
3668 * dwUnloadDelay [I] Unload delay in milliseconds.
3669 * dwReserved [I] Reserved. Set to 0.
3670 *
3671 * RETURNS
3672 * Nothing.
3673 *
3674 * SEE ALSO
3675 * CoLoadLibrary, CoFreeAllLibraries, CoFreeLibrary
3676 */
3678{
3679 struct apartment *apt = COM_CurrentApt();
3680 if (!apt)
3681 {
3682 ERR("apartment not initialised\n");
3683 return;
3684 }
3685
3686 apartment_freeunusedlibraries(apt, dwUnloadDelay);
3687}
3688
3689/***********************************************************************
3690 * CoFreeUnusedLibraries [OLE32.@]
3691 *
3692 * Frees any unused libraries. Unused are identified as those that return
3693 * S_OK from their DllCanUnloadNow function.
3694 *
3695 * RETURNS
3696 * Nothing.
3697 *
3698 * SEE ALSO
3699 * CoLoadLibrary, CoFreeAllLibraries, CoFreeLibrary
3700 */
3702{
3704}
3705
3706/***********************************************************************
3707 * CoFileTimeNow [OLE32.@]
3708 *
3709 * Retrieves the current time in FILETIME format.
3710 *
3711 * PARAMS
3712 * lpFileTime [O] The current time.
3713 *
3714 * RETURNS
3715 * S_OK.
3716 */
3718{
3719 GetSystemTimeAsFileTime( lpFileTime );
3720 return S_OK;
3721}
3722
3723/******************************************************************************
3724 * CoLockObjectExternal [OLE32.@]
3725 *
3726 * Increments or decrements the external reference count of a stub object.
3727 *
3728 * PARAMS
3729 * pUnk [I] Stub object.
3730 * fLock [I] If TRUE then increments the external ref-count,
3731 * otherwise decrements.
3732 * fLastUnlockReleases [I] If TRUE then the last unlock has the effect of
3733 * calling CoDisconnectObject.
3734 *
3735 * RETURNS
3736 * Success: S_OK.
3737 * Failure: HRESULT code.
3738 *
3739 * NOTES
3740 * If fLock is TRUE and an object is passed in that doesn't have a stub
3741 * manager then a new stub manager is created for the object.
3742 */
3745 BOOL fLock,
3746 BOOL fLastUnlockReleases)
3747{
3748 struct stub_manager *stubmgr;
3749 struct apartment *apt;
3750
3751 TRACE("pUnk=%p, fLock=%s, fLastUnlockReleases=%s\n",
3752 pUnk, fLock ? "TRUE" : "FALSE", fLastUnlockReleases ? "TRUE" : "FALSE");
3753
3754 if (!(apt = apartment_get_current_or_mta()))
3755 {
3756 ERR("apartment not initialised\n");
3757 return CO_E_NOTINITIALIZED;
3758 }
3759
3760 stubmgr = get_stub_manager_from_object(apt, pUnk, fLock);
3761 if (!stubmgr)
3762 {
3763 WARN("stub object not found %p\n", pUnk);
3764 /* Note: native is pretty broken here because it just silently
3765 * fails, without returning an appropriate error code, making apps
3766 * think that the object was disconnected, when it actually wasn't */
3767 apartment_release(apt);
3768 return S_OK;
3769 }
3770
3771 if (fLock)
3772 stub_manager_ext_addref(stubmgr, 1, FALSE);
3773 else
3774 stub_manager_ext_release(stubmgr, 1, FALSE, fLastUnlockReleases);
3775
3776 stub_manager_int_release(stubmgr);
3777 apartment_release(apt);
3778 return S_OK;
3779}
3780
3781/***********************************************************************
3782 * CoInitializeWOW (OLE32.@)
3783 *
3784 * WOW equivalent of CoInitialize?
3785 *
3786 * PARAMS
3787 * x [I] Unknown.
3788 * y [I] Unknown.
3789 *
3790 * RETURNS
3791 * Unknown.
3792 */
3794{
3795 FIXME("(0x%08x,0x%08x),stub!\n",x,y);
3796 return 0;
3797}
3798
3799/***********************************************************************
3800 * CoGetState [OLE32.@]
3801 *
3802 * Retrieves the thread state object previously stored by CoSetState().
3803 *
3804 * PARAMS
3805 * ppv [I] Address where pointer to object will be stored.
3806 *
3807 * RETURNS
3808 * Success: S_OK.
3809 * Failure: E_OUTOFMEMORY.
3810 *
3811 * NOTES
3812 * Crashes on all invalid ppv addresses, including NULL.
3813 * If the function returns a non-NULL object then the caller must release its
3814 * reference on the object when the object is no longer required.
3815 *
3816 * SEE ALSO
3817 * CoSetState().
3818 */
3820{
3821 struct oletls *info = COM_CurrentInfo();
3822 if (!info) return E_OUTOFMEMORY;
3823
3824 *ppv = NULL;
3825
3826 if (info->state)
3827 {
3828 IUnknown_AddRef(info->state);
3829 *ppv = info->state;
3830 TRACE("apt->state=%p\n", info->state);
3831 }
3832
3833 return S_OK;
3834}
3835
3836/***********************************************************************
3837 * CoSetState [OLE32.@]
3838 *
3839 * Sets the thread state object.
3840 *
3841 * PARAMS
3842 * pv [I] Pointer to state object to be stored.
3843 *
3844 * NOTES
3845 * The system keeps a reference on the object while the object stored.
3846 *
3847 * RETURNS
3848 * Success: S_OK.
3849 * Failure: E_OUTOFMEMORY.
3850 */
3852{
3853 struct oletls *info = COM_CurrentInfo();
3854 if (!info) return E_OUTOFMEMORY;
3855
3856 if (pv) IUnknown_AddRef(pv);
3857
3858 if (info->state)
3859 {
3860 TRACE("-- release %p now\n", info->state);
3861 IUnknown_Release(info->state);
3862 }
3863
3864 info->state = pv;
3865
3866 return S_OK;
3867}
3868
3869
3870/******************************************************************************
3871 * CoTreatAsClass [OLE32.@]
3872 *
3873 * Sets the TreatAs value of a class.
3874 *
3875 * PARAMS
3876 * clsidOld [I] Class to set TreatAs value on.
3877 * clsidNew [I] The class the clsidOld should be treated as.
3878 *
3879 * RETURNS
3880 * Success: S_OK.
3881 * Failure: HRESULT code.
3882 *
3883 * SEE ALSO
3884 * CoGetTreatAsClass
3885 */
3887{
3888 static const WCHAR wszAutoTreatAs[] = {'A','u','t','o','T','r','e','a','t','A','s',0};
3889 static const WCHAR wszTreatAs[] = {'T','r','e','a','t','A','s',0};
3890 HKEY hkey = NULL;
3891 WCHAR szClsidNew[CHARS_IN_GUID];
3892 HRESULT res = S_OK;
3893 WCHAR auto_treat_as[CHARS_IN_GUID];
3894 LONG auto_treat_as_size = sizeof(auto_treat_as);
3895 CLSID id;
3896
3897 res = COM_OpenKeyForCLSID(clsidOld, NULL, KEY_READ | KEY_WRITE, &hkey);
3898 if (FAILED(res))
3899 goto done;
3900
3901 if (IsEqualGUID( clsidOld, clsidNew ))
3902 {
3903 if (!RegQueryValueW(hkey, wszAutoTreatAs, auto_treat_as, &auto_treat_as_size) &&
3904 CLSIDFromString(auto_treat_as, &id) == S_OK)
3905 {
3906 if (RegSetValueW(hkey, wszTreatAs, REG_SZ, auto_treat_as, sizeof(auto_treat_as)))
3907 {
3909 goto done;
3910 }
3911 }
3912 else
3913 {
3914 if(RegDeleteKeyW(hkey, wszTreatAs))
3916 goto done;
3917 }
3918 }
3919 else
3920 {
3921 if(IsEqualGUID(clsidNew, &CLSID_NULL)){
3922 RegDeleteKeyW(hkey, wszTreatAs);
3923 }else{
3924 if(!StringFromGUID2(clsidNew, szClsidNew, ARRAY_SIZE(szClsidNew))){
3925 WARN("StringFromGUID2 failed\n");
3926 res = E_FAIL;
3927 goto done;
3928 }
3929
3930 if(RegSetValueW(hkey, wszTreatAs, REG_SZ, szClsidNew, sizeof(szClsidNew)) != ERROR_SUCCESS){
3931 WARN("RegSetValue failed\n");
3933 goto done;
3934 }
3935 }
3936 }
3937
3938done:
3939 if (hkey) RegCloseKey(hkey);
3940 return res;
3941}
3942
3943/******************************************************************************
3944 * CoGetTreatAsClass [OLE32.@]
3945 *
3946 * Gets the TreatAs value of a class.
3947 *
3948 * PARAMS
3949 * clsidOld [I] Class to get the TreatAs value of.
3950 * clsidNew [I] The class the clsidOld should be treated as.
3951 *
3952 * RETURNS
3953 * Success: S_OK.
3954 * Failure: HRESULT code.
3955 *
3956 * SEE ALSO
3957 * CoSetTreatAsClass
3958 */
3960{
3961 static const WCHAR wszTreatAs[] = {'T','r','e','a','t','A','s',0};
3962 HKEY hkey = NULL;
3963 WCHAR szClsidNew[CHARS_IN_GUID];
3964 HRESULT res = S_OK;
3965 LONG len = sizeof(szClsidNew);
3966
3967 TRACE("(%s,%p)\n", debugstr_guid(clsidOld), clsidNew);
3968
3969 if (!clsidOld || !clsidNew)
3970 return E_INVALIDARG;
3971
3972 *clsidNew = *clsidOld; /* copy over old value */
3973
3974 res = COM_OpenKeyForCLSID(clsidOld, wszTreatAs, KEY_READ, &hkey);
3975 if (FAILED(res))
3976 {
3977 res = S_FALSE;
3978 goto done;
3979 }
3980 if (RegQueryValueW(hkey, NULL, szClsidNew, &len))
3981 {
3982 res = S_FALSE;
3983 goto done;
3984 }
3985 res = CLSIDFromString(szClsidNew,clsidNew);
3986 if (FAILED(res))
3987 ERR("Failed CLSIDFromStringA(%s), hres 0x%08x\n", debugstr_w(szClsidNew), res);
3988done:
3989 if (hkey) RegCloseKey(hkey);
3990 return res;
3991}
3992
3993/******************************************************************************
3994 * CoGetCurrentProcess [OLE32.@]
3995 *
3996 * Gets the current process ID.
3997 *
3998 * RETURNS
3999 * The current process ID.
4000 *
4001 * NOTES
4002 * Is DWORD really the correct return type for this function?
4003 */
4005{
4006 return GetCurrentProcessId();
4007}
4008
4009/***********************************************************************
4010 * CoGetCurrentLogicalThreadId [OLE32.@]
4011 */
4013{
4014 TRACE("(%p)\n", id);
4015
4016 if (!id)
4017 return E_INVALIDARG;
4018
4019 *id = COM_CurrentCausalityId();
4020 return S_OK;
4021}
4022
4023/******************************************************************************
4024 * CoRegisterMessageFilter [OLE32.@]
4025 *
4026 * Registers a message filter.
4027 *
4028 * PARAMS
4029 * lpMessageFilter [I] Pointer to interface.
4030 * lplpMessageFilter [O] Indirect pointer to prior instance if non-NULL.
4031 *
4032 * RETURNS
4033 * Success: S_OK.
4034 * Failure: HRESULT code.
4035 *
4036 * NOTES
4037 * Both lpMessageFilter and lplpMessageFilter are optional. Passing in a NULL
4038 * lpMessageFilter removes the message filter.
4039 *
4040 * If lplpMessageFilter is not NULL the previous message filter will be
4041 * returned in the memory pointer to this parameter and the caller is
4042 * responsible for releasing the object.
4043 *
4044 * The current thread be in an apartment otherwise the function will crash.
4045 */
4047 LPMESSAGEFILTER lpMessageFilter,
4048 LPMESSAGEFILTER *lplpMessageFilter)
4049{
4050 struct apartment *apt;
4051 IMessageFilter *lpOldMessageFilter;
4052
4053 TRACE("(%p, %p)\n", lpMessageFilter, lplpMessageFilter);
4054
4055 apt = COM_CurrentApt();
4056
4057 /* can't set a message filter in a multi-threaded apartment */
4058 if (!apt || apt->multi_threaded)
4059 {
4060 WARN("can't set message filter in MTA or uninitialized apt\n");
4061 return CO_E_NOT_SUPPORTED;
4062 }
4063
4064 if (lpMessageFilter)
4065 IMessageFilter_AddRef(lpMessageFilter);
4066
4067 EnterCriticalSection(&apt->cs);
4068
4069 lpOldMessageFilter = apt->filter;
4070 apt->filter = lpMessageFilter;
4071
4072 LeaveCriticalSection(&apt->cs);
4073
4074 if (lplpMessageFilter)
4075 *lplpMessageFilter = lpOldMessageFilter;
4076 else if (lpOldMessageFilter)
4077 IMessageFilter_Release(lpOldMessageFilter);
4078
4079 return S_OK;
4080}
4081
4082/***********************************************************************
4083 * CoIsOle1Class [OLE32.@]
4084 *
4085 * Determines whether the specified class an OLE v1 class.
4086 *
4087 * PARAMS
4088 * clsid [I] Class to test.
4089 *
4090 * RETURNS
4091 * TRUE if the class is an OLE v1 class, or FALSE otherwise.
4092 */
4094{
4095 FIXME("%s\n", debugstr_guid(clsid));
4096 return FALSE;
4097}
4098
4099/***********************************************************************
4100 * IsEqualGUID [OLE32.@]
4101 *
4102 * Compares two Unique Identifiers.
4103 *
4104 * PARAMS
4105 * rguid1 [I] The first GUID to compare.
4106 * rguid2 [I] The other GUID to compare.
4107 *
4108 * RETURNS
4109 * TRUE if equal
4110 */
4111#undef IsEqualGUID
4113 REFGUID rguid1,
4114 REFGUID rguid2)
4115{
4116 return !memcmp(rguid1,rguid2,sizeof(GUID));
4117}
4118
4119/***********************************************************************
4120 * CoInitializeSecurity [OLE32.@]
4121 */
4123 SOLE_AUTHENTICATION_SERVICE* asAuthSvc,
4124 void* pReserved1, DWORD dwAuthnLevel,
4125 DWORD dwImpLevel, void* pReserved2,
4126 DWORD dwCapabilities, void* pReserved3)
4127{
4128 FIXME("(%p,%d,%p,%p,%d,%d,%p,%d,%p) - stub!\n", pSecDesc, cAuthSvc,
4129 asAuthSvc, pReserved1, dwAuthnLevel, dwImpLevel, pReserved2,
4130 dwCapabilities, pReserved3);
4131 return S_OK;
4132}
4133
4134/***********************************************************************
4135 * CoSuspendClassObjects [OLE32.@]
4136 *
4137 * Suspends all registered class objects to prevent further requests coming in
4138 * for those objects.
4139 *
4140 * RETURNS
4141 * Success: S_OK.
4142 * Failure: HRESULT code.
4143 */
4145{
4146 FIXME("\n");
4147 return S_OK;
4148}
4149
4150/***********************************************************************
4151 * CoAddRefServerProcess [OLE32.@]
4152 *
4153 * Helper function for incrementing the reference count of a local-server
4154 * process.
4155 *
4156 * RETURNS
4157 * New reference count.
4158 *
4159 * SEE ALSO
4160 * CoReleaseServerProcess().
4161 */
4163{
4164 ULONG refs;
4165
4166 TRACE("\n");
4167
4171
4172 TRACE("refs before: %d\n", refs - 1);
4173
4174 return refs;
4175}
4176
4177/***********************************************************************
4178 * CoReleaseServerProcess [OLE32.@]
4179 *
4180 * Helper function for decrementing the reference count of a local-server
4181 * process.
4182 *
4183 * RETURNS
4184 * New reference count.
4185 *
4186 * NOTES
4187 * When reference count reaches 0, this function suspends all registered
4188 * classes so no new connections are accepted.
4189 *
4190 * SEE ALSO
4191 * CoAddRefServerProcess(), CoSuspendClassObjects().
4192 */
4194{
4195 ULONG refs;
4196
4197 TRACE("\n");
4198
4200
4202 /* FIXME: if (!refs) COM_SuspendClassObjects(); */
4203
4205
4206 TRACE("refs after: %d\n", refs);
4207
4208 return refs;
4209}
4210
4211/***********************************************************************
4212 * CoIsHandlerConnected [OLE32.@]
4213 *
4214 * Determines whether a proxy is connected to a remote stub.
4215 *
4216 * PARAMS
4217 * pUnk [I] Pointer to object that may or may not be connected.
4218 *
4219 * RETURNS
4220 * TRUE if pUnk is not a proxy or if pUnk is connected to a remote stub, or
4221 * FALSE otherwise.
4222 */
4224{
4225 FIXME("%p\n", pUnk);
4226
4227 return TRUE;
4228}
4229
4230/***********************************************************************
4231 * CoAllowSetForegroundWindow [OLE32.@]
4232 *
4233 */
4235{
4236 FIXME("(%p, %p): stub\n", pUnk, pvReserved);
4237 return S_OK;
4238}
4239
4240/***********************************************************************
4241 * CoQueryProxyBlanket [OLE32.@]
4242 *
4243 * Retrieves the security settings being used by a proxy.
4244 *
4245 * PARAMS
4246 * pProxy [I] Pointer to the proxy object.
4247 * pAuthnSvc [O] The type of authentication service.
4248 * pAuthzSvc [O] The type of authorization service.
4249 * ppServerPrincName [O] Optional. The server prinicple name.
4250 * pAuthnLevel [O] The authentication level.
4251 * pImpLevel [O] The impersonation level.
4252 * ppAuthInfo [O] Information specific to the authorization/authentication service.
4253 * pCapabilities [O] Flags affecting the security behaviour.
4254 *
4255 * RETURNS
4256 * Success: S_OK.
4257 * Failure: HRESULT code.
4258 *
4259 * SEE ALSO
4260 * CoCopyProxy, CoSetProxyBlanket.
4261 */
4263 DWORD *pAuthzSvc, OLECHAR **ppServerPrincName, DWORD *pAuthnLevel,
4264 DWORD *pImpLevel, void **ppAuthInfo, DWORD *pCapabilities)
4265{
4266 IClientSecurity *pCliSec;
4267 HRESULT hr;
4268
4269 TRACE("%p\n", pProxy);
4270
4271 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (void **)&pCliSec);
4272 if (SUCCEEDED(hr))
4273 {
4274 hr = IClientSecurity_QueryBlanket(pCliSec, pProxy, pAuthnSvc,
4275 pAuthzSvc, ppServerPrincName,
4276 pAuthnLevel, pImpLevel, ppAuthInfo,
4277 pCapabilities);
4278 IClientSecurity_Release(pCliSec);
4279 }
4280
4281 if (FAILED(hr)) ERR("-- failed with 0x%08x\n", hr);
4282 return hr;
4283}
4284
4285/***********************************************************************
4286 * CoSetProxyBlanket [OLE32.@]
4287 *
4288 * Sets the security settings for a proxy.
4289 *
4290 * PARAMS
4291 * pProxy [I] Pointer to the proxy object.
4292 * AuthnSvc [I] The type of authentication service.
4293 * AuthzSvc [I] The type of authorization service.
4294 * pServerPrincName [I] The server prinicple name.
4295 * AuthnLevel [I] The authentication level.
4296 * ImpLevel [I] The impersonation level.
4297 * pAuthInfo [I] Information specific to the authorization/authentication service.
4298 * Capabilities [I] Flags affecting the security behaviour.
4299 *
4300 * RETURNS
4301 * Success: S_OK.
4302 * Failure: HRESULT code.
4303 *
4304 * SEE ALSO
4305 * CoQueryProxyBlanket, CoCopyProxy.
4306 */
4308 DWORD AuthzSvc, OLECHAR *pServerPrincName, DWORD AuthnLevel,
4309 DWORD ImpLevel, void *pAuthInfo, DWORD Capabilities)
4310{
4311 IClientSecurity *pCliSec;
4312 HRESULT hr;
4313
4314 TRACE("%p\n", pProxy);
4315
4316 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (void **)&pCliSec);
4317 if (SUCCEEDED(hr))
4318 {
4319 hr = IClientSecurity_SetBlanket(pCliSec, pProxy, AuthnSvc,
4320 AuthzSvc, pServerPrincName,
4321 AuthnLevel, ImpLevel, pAuthInfo,
4322 Capabilities);
4323 IClientSecurity_Release(pCliSec);
4324 }
4325
4326 if (FAILED(hr)) ERR("-- failed with 0x%08x\n", hr);
4327 return hr;
4328}
4329
4330/***********************************************************************
4331 * CoCopyProxy [OLE32.@]
4332 *
4333 * Copies a proxy.
4334 *
4335 * PARAMS
4336 * pProxy [I] Pointer to the proxy object.
4337 * ppCopy [O] Copy of the proxy.
4338 *
4339 * RETURNS
4340 * Success: S_OK.
4341 * Failure: HRESULT code.
4342 *
4343 * SEE ALSO
4344 * CoQueryProxyBlanket, CoSetProxyBlanket.
4345 */
4347{
4348 IClientSecurity *pCliSec;
4349 HRESULT hr;
4350
4351 TRACE("%p\n", pProxy);
4352
4353 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (void **)&pCliSec);
4354 if (SUCCEEDED(hr))
4355 {
4356 hr = IClientSecurity_CopyProxy(pCliSec, pProxy, ppCopy);
4357 IClientSecurity_Release(pCliSec);
4358 }
4359
4360 if (FAILED(hr)) ERR("-- failed with 0x%08x\n", hr);
4361 return hr;
4362}
4363
4364
4365/***********************************************************************
4366 * CoGetCallContext [OLE32.@]
4367 *
4368 * Gets the context of the currently executing server call in the current
4369 * thread.
4370 *
4371 * PARAMS
4372 * riid [I] Context interface to return.
4373 * ppv [O] Pointer to memory that will receive the context on return.
4374 *
4375 * RETURNS
4376 * Success: S_OK.
4377 * Failure: HRESULT code.
4378 */
4380{
4381 struct oletls *info = COM_CurrentInfo();
4382
4383 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
4384
4385 if (!info)
4386 return E_OUTOFMEMORY;
4387
4388 if (!info->call_state)
4389 return RPC_E_CALL_COMPLETE;
4390
4391 return IUnknown_QueryInterface(info->call_state, riid, ppv);
4392}
4393
4394/***********************************************************************
4395 * CoSwitchCallContext [OLE32.@]
4396 *
4397 * Switches the context of the currently executing server call in the current
4398 * thread.
4399 *
4400 * PARAMS
4401 * pObject [I] Pointer to new context object
4402 * ppOldObject [O] Pointer to memory that will receive old context object pointer
4403 *
4404 * RETURNS
4405 * Success: S_OK.
4406 * Failure: HRESULT code.
4407 */
4409{
4410 struct oletls *info = COM_CurrentInfo();
4411
4412 TRACE("(%p, %p)\n", pObject, ppOldObject);
4413
4414 if (!info)
4415 return E_OUTOFMEMORY;
4416
4417 *ppOldObject = info->call_state;
4418 info->call_state = pObject; /* CoSwitchCallContext does not addref nor release objects */
4419
4420 return S_OK;
4421}
4422
4423/***********************************************************************
4424 * CoQueryClientBlanket [OLE32.@]
4425 *
4426 * Retrieves the authentication information about the client of the currently
4427 * executing server call in the current thread.
4428 *
4429 * PARAMS
4430 * pAuthnSvc [O] Optional. The type of authentication service.
4431 * pAuthzSvc [O] Optional. The type of authorization service.
4432 * pServerPrincName [O] Optional. The server prinicple name.
4433 * pAuthnLevel [O] Optional. The authentication level.
4434 * pImpLevel [O] Optional. The impersonation level.
4435 * pPrivs [O] Optional. Information about the privileges of the client.
4436 * pCapabilities [IO] Optional. Flags affecting the security behaviour.
4437 *
4438 * RETURNS
4439 * Success: S_OK.
4440 * Failure: HRESULT code.
4441 *
4442 * SEE ALSO
4443 * CoImpersonateClient, CoRevertToSelf, CoGetCallContext.
4444 */
4446 DWORD *pAuthnSvc,
4447 DWORD *pAuthzSvc,
4448 OLECHAR **pServerPrincName,
4449 DWORD *pAuthnLevel,
4450 DWORD *pImpLevel,
4451 RPC_AUTHZ_HANDLE *pPrivs,
4452 DWORD *pCapabilities)
4453{
4454 IServerSecurity *pSrvSec;
4455 HRESULT hr;
4456
4457 TRACE("(%p, %p, %p, %p, %p, %p, %p)\n",
4458 pAuthnSvc, pAuthzSvc, pServerPrincName, pAuthnLevel, pImpLevel,
4459 pPrivs, pCapabilities);
4460
4461 hr = CoGetCallContext(&IID_IServerSecurity, (void **)&pSrvSec);
4462 if (SUCCEEDED(hr))
4463 {
4464 hr = IServerSecurity_QueryBlanket(
4465 pSrvSec, pAuthnSvc, pAuthzSvc, pServerPrincName, pAuthnLevel,
4466 pImpLevel, pPrivs, pCapabilities);
4467 IServerSecurity_Release(pSrvSec);
4468 }
4469
4470 return hr;
4471}
4472
4473/***********************************************************************
4474 * CoImpersonateClient [OLE32.@]
4475 *
4476 * Impersonates the client of the currently executing server call in the
4477 * current thread.
4478 *
4479 * PARAMS
4480 * None.
4481 *
4482 * RETURNS
4483 * Success: S_OK.
4484 * Failure: HRESULT code.
4485 *
4486 * NOTES
4487 * If this function fails then the current thread will not be impersonating
4488 * the client and all actions will take place on behalf of the server.
4489 * Therefore, it is important to check the return value from this function.
4490 *
4491 * SEE ALSO
4492 * CoRevertToSelf, CoQueryClientBlanket, CoGetCallContext.
4493 */
4495{
4496 IServerSecurity *pSrvSec;
4497 HRESULT hr;
4498
4499 TRACE("\n");
4500
4501 hr = CoGetCallContext(&IID_IServerSecurity, (void **)&pSrvSec);
4502 if (SUCCEEDED(hr))
4503 {
4504 hr = IServerSecurity_ImpersonateClient(pSrvSec);
4505 IServerSecurity_Release(pSrvSec);
4506 }
4507
4508 return hr;
4509}
4510
4511/***********************************************************************
4512 * CoRevertToSelf [OLE32.@]
4513 *
4514 * Ends the impersonation of the client of the currently executing server
4515 * call in the current thread.
4516 *
4517 * PARAMS
4518 * None.
4519 *
4520 * RETURNS
4521 * Success: S_OK.
4522 * Failure: HRESULT code.
4523 *
4524 * SEE ALSO
4525 * CoImpersonateClient, CoQueryClientBlanket, CoGetCallContext.
4526 */
4528{
4529 IServerSecurity *pSrvSec;
4530 HRESULT hr;
4531
4532 TRACE("\n");
4533
4534 hr = CoGetCallContext(&IID_IServerSecurity, (void **)&pSrvSec);
4535 if (SUCCEEDED(hr))
4536 {
4537 hr = IServerSecurity_RevertToSelf(pSrvSec);
4538 IServerSecurity_Release(pSrvSec);
4539 }
4540
4541 return hr;
4542}
4543
4545{
4546 /* first try to retrieve messages for incoming COM calls to the apartment window */
4547 return (apt->win && PeekMessageW(msg, apt->win, 0, 0, PM_REMOVE|PM_NOYIELD)) ||
4548 /* next retrieve other messages necessary for the app to remain responsive */
4550 PeekMessageW(msg, NULL, 0, 0, PM_QS_PAINT|PM_QS_SENDMESSAGE|PM_REMOVE|PM_NOYIELD);
4551}
4552
4553/***********************************************************************
4554 * CoWaitForMultipleHandles [OLE32.@]
4555 *
4556 * Waits for one or more handles to become signaled.
4557 *
4558 * PARAMS
4559 * dwFlags [I] Flags. See notes.
4560 * dwTimeout [I] Timeout in milliseconds.
4561 * cHandles [I] Number of handles pointed to by pHandles.
4562 * pHandles [I] Handles to wait for.
4563 * lpdwindex [O] Index of handle that was signaled.
4564 *
4565 * RETURNS
4566 * Success: S_OK.
4567 * Failure: RPC_S_CALLPENDING on timeout.
4568 *
4569 * NOTES
4570 *
4571 * The dwFlags parameter can be zero or more of the following:
4572 *| COWAIT_WAITALL - Wait for all of the handles to become signaled.
4573 *| COWAIT_ALERTABLE - Allows a queued APC to run during the wait.
4574 *
4575 * SEE ALSO
4576 * MsgWaitForMultipleObjects, WaitForMultipleObjects.
4577 */
4579 ULONG cHandles, LPHANDLE pHandles, LPDWORD lpdwindex)
4580{
4581 HRESULT hr = S_OK;
4582 DWORD start_time = GetTickCount();
4584 BOOL message_loop = apt && !apt->multi_threaded;
4585 BOOL check_apc = (dwFlags & COWAIT_ALERTABLE) != 0;
4586 BOOL post_quit = FALSE;
4588
4589 TRACE("(0x%08x, 0x%08x, %d, %p, %p)\n", dwFlags, dwTimeout, cHandles,
4590 pHandles, lpdwindex);
4591
4592 if (!lpdwindex)
4593 return E_INVALIDARG;
4594
4595 *lpdwindex = 0;
4596
4597 if (!pHandles)
4598 return E_INVALIDARG;
4599
4600 if (!cHandles)
4601 return RPC_E_NO_SYNC;
4602
4603 while (TRUE)
4604 {
4606 DWORD res;
4607
4608 if (now - start_time > dwTimeout)
4609 {
4611 break;
4612 }
4613
4614 if (message_loop)
4615 {
4616 DWORD wait_flags = ((dwFlags & COWAIT_WAITALL) ? MWMO_WAITALL : 0) |
4618
4619 TRACE("waiting for rpc completion or window message\n");
4620
4621 res = WAIT_TIMEOUT;
4622
4623 if (check_apc)
4624 {
4625 res = WaitForMultipleObjectsEx(cHandles, pHandles,
4626 (dwFlags & COWAIT_WAITALL) != 0, 0, TRUE);
4627 check_apc = FALSE;
4628 }
4629
4630 if (res == WAIT_TIMEOUT)
4631 res = MsgWaitForMultipleObjectsEx(cHandles, pHandles,
4632 (dwTimeout == INFINITE) ? INFINITE : start_time + dwTimeout - now,
4633 QS_SENDMESSAGE | QS_ALLPOSTMESSAGE | QS_PAINT, wait_flags);
4634
4635 if (res == WAIT_OBJECT_0 + cHandles) /* messages available */
4636 {
4637 MSG msg;
4638 int count = 0;
4639
4640 /* call message filter */
4641
4642 if (COM_CurrentApt()->filter)
4643 {
4644 PENDINGTYPE pendingtype =
4645 COM_CurrentInfo()->pending_call_count_server ?
4646 PENDINGTYPE_NESTED : PENDINGTYPE_TOPLEVEL;
4647 DWORD be_handled = IMessageFilter_MessagePending(
4648 COM_CurrentApt()->filter, 0 /* FIXME */,
4649 now - start_time, pendingtype);
4650 TRACE("IMessageFilter_MessagePending returned %d\n", be_handled);
4651 switch (be_handled)
4652 {
4653 case PENDINGMSG_CANCELCALL:
4654 WARN("call canceled\n");
4656 break;
4657 case PENDINGMSG_WAITNOPROCESS:
4658 case PENDINGMSG_WAITDEFPROCESS:
4659 default:
4660 /* FIXME: MSDN is very vague about the difference
4661 * between WAITNOPROCESS and WAITDEFPROCESS - there
4662 * appears to be none, so it is possibly a left-over
4663 * from the 16-bit world. */
4664 break;
4665 }
4666 }
4667
4668 if (!apt->win)
4669 {
4670 /* If window is NULL on apartment, peek at messages so that it will not trigger
4671 * MsgWaitForMultipleObjects next time. */
4672 PeekMessageW(NULL, NULL, 0, 0, PM_QS_POSTMESSAGE | PM_NOREMOVE | PM_NOYIELD);
4673 }
4674 /* some apps (e.g. Visio 2010) don't handle WM_PAINT properly and loop forever,
4675 * so after processing 100 messages we go back to checking the wait handles */
4676 while (count++ < 100 && COM_PeekMessage(apt, &msg))
4677 {
4678 if (msg.message == WM_QUIT)
4679 {
4680 TRACE("received WM_QUIT message\n");
4681 post_quit = TRUE;
4682 exit_code = msg.wParam;
4683 }
4684 else
4685 {
4686 TRACE("received message whilst waiting for RPC: 0x%04x\n", msg.message);
4689 }
4690 }
4691 continue;
4692 }
4693 }
4694 else
4695 {
4696 TRACE("waiting for rpc completion\n");
4697
4698 res = WaitForMultipleObjectsEx(cHandles, pHandles, (dwFlags & COWAIT_WAITALL) != 0,
4699 (dwTimeout == INFINITE) ? INFINITE : start_time + dwTimeout - now,
4700 (dwFlags & COWAIT_ALERTABLE) != 0);
4701 }
4702
4703 switch (res)
4704 {
4705 case WAIT_TIMEOUT:
4707 break;
4708 case WAIT_FAILED:
4710 break;
4711 default:
4712 *lpdwindex = res;
4713 break;
4714 }
4715 break;
4716 }
4717 if (post_quit) PostQuitMessage(exit_code);
4718 TRACE("-- 0x%08x\n", hr);
4719 return hr;
4720}
4721
4722
4723/***********************************************************************
4724 * CoGetObject [OLE32.@]
4725 *
4726 * Gets the object named by converting the name to a moniker and binding to it.
4727 *
4728 * PARAMS
4729 * pszName [I] String representing the object.
4730 * pBindOptions [I] Parameters affecting the binding to the named object.
4731 * riid [I] Interface to bind to on the objecct.
4732 * ppv [O] On output, the interface riid of the object represented
4733 * by pszName.
4734 *
4735 * RETURNS
4736 * Success: S_OK.
4737 * Failure: HRESULT code.
4738 *
4739 * SEE ALSO
4740 * MkParseDisplayName.
4741 */
4742HRESULT WINAPI CoGetObject(LPCWSTR pszName, BIND_OPTS *pBindOptions,
4743 REFIID riid, void **ppv)
4744{
4745 IBindCtx *pbc;
4746 HRESULT hr;
4747
4748 *ppv = NULL;
4749
4750 hr = CreateBindCtx(0, &pbc);
4751 if (SUCCEEDED(hr))
4752 {
4753 if (pBindOptions)
4754 hr = IBindCtx_SetBindOptions(pbc, pBindOptions);
4755
4756 if (SUCCEEDED(hr))
4757 {
4758 ULONG chEaten;
4759 IMoniker *pmk;
4760
4761 hr = MkParseDisplayName(pbc, pszName, &chEaten, &pmk);
4762 if (SUCCEEDED(hr))
4763 {
4764 hr = IMoniker_BindToObject(pmk, pbc, NULL, riid, ppv);
4765 IMoniker_Release(pmk);
4766 }
4767 }
4768
4769 IBindCtx_Release(pbc);
4770 }
4771 return hr;
4772}
4773
4774/***********************************************************************
4775 * CoRegisterChannelHook [OLE32.@]
4776 *
4777 * Registers a process-wide hook that is called during ORPC calls.
4778 *
4779 * PARAMS
4780 * guidExtension [I] GUID of the channel hook to register.
4781 * pChannelHook [I] Channel hook object to register.
4782 *
4783 * RETURNS
4784 * Success: S_OK.
4785 * Failure: HRESULT code.
4786 */
4788{
4789 TRACE("(%s, %p)\n", debugstr_guid(guidExtension), pChannelHook);
4790
4791 return RPC_RegisterChannelHook(guidExtension, pChannelHook);
4792}
4793
4794typedef struct Context
4795{
4801
4803{
4804 return CONTAINING_RECORD(iface, Context, IComThreadingInfo_iface);
4805}
4806
4808{
4809 return CONTAINING_RECORD(iface, Context, IContextCallback_iface);
4810}
4811
4813{
4814 return CONTAINING_RECORD(iface, Context, IObjContext_iface);
4815}
4816
4818{
4819 *ppv = NULL;
4820
4821 if (IsEqualIID(riid, &IID_IComThreadingInfo) ||
4823 {
4824 *ppv = &iface->IComThreadingInfo_iface;
4825 }
4826 else if (IsEqualIID(riid, &IID_IContextCallback))
4827 {
4828 *ppv = &iface->IContextCallback_iface;
4829 }
4830 else if (IsEqualIID(riid, &IID_IObjContext))
4831 {
4832 *ppv = &iface->IObjContext_iface;
4833 }
4834
4835 if (*ppv)
4836 {
4837 IUnknown_AddRef((IUnknown*)*ppv);
4838 return S_OK;
4839 }
4840
4841 FIXME("interface not implemented %s\n", debugstr_guid(riid));
4842 return E_NOINTERFACE;
4843}
4844
4846{
4847 return InterlockedIncrement(&This->refs);
4848}
4849
4851{
4852 /* Context instance is initially created with CoGetContextToken() with refcount set to 0,
4853 releasing context while refcount is at 0 destroys it. */
4854 if (!This->refs)
4855 {
4857 return 0;
4858 }
4859
4860 return InterlockedDecrement(&This->refs);
4861}
4862
4864{
4867}
4868
4870{
4872 return Context_AddRef(This);
4873}
4874
4876{
4878 return Context_Release(This);
4879}
4880
4882{
4884
4885 TRACE("(%p)\n", apttype);
4886
4887 return CoGetApartmentType(apttype, &qualifier);
4888}
4889
4891{
4893 APTTYPE apttype;
4894 HRESULT hr;
4895
4896 hr = CoGetApartmentType(&apttype, &qualifier);
4897 if (FAILED(hr))
4898 return hr;
4899
4900 TRACE("(%p)\n", thdtype);
4901
4902 switch (apttype)
4903 {
4904 case APTTYPE_STA:
4905 case APTTYPE_MAINSTA:
4906 *thdtype = THDTYPE_PROCESSMESSAGES;
4907 break;
4908 default:
4909 *thdtype = THDTYPE_BLOCKMESSAGES;
4910 break;
4911 }
4912 return S_OK;
4913}
4914
4916{
4917 TRACE("(%p)\n", logical_thread_id);
4918 return CoGetCurrentLogicalThreadId(logical_thread_id);
4919}
4920
4922{
4923 FIXME("(%s): stub\n", debugstr_guid(logical_thread_id));
4924 return E_NOTIMPL;
4925}
4926
4927static const IComThreadingInfoVtbl Context_Threading_Vtbl =
4928{
4936};
4937
4939{
4942}
4943
4945{
4947 return Context_AddRef(This);
4948}
4949
4951{
4953 return Context_Release(This);
4954}
4955
4958{
4960
4961 FIXME("(%p/%p)->(%p, %p, %s, %d, %p)\n", This, iface, pCallback, param, debugstr_guid(riid), method, punk);
4962 return E_NOTIMPL;
4963}
4964
4965static const IContextCallbackVtbl Context_Callback_Vtbl =
4966{
4971};
4972
4974{
4977}
4978
4980{
4982 return Context_AddRef(This);
4983}
4984
4986{
4988 return Context_Release(This);
4989}
4990
4992{
4994
4995 FIXME("(%p/%p)->(%s, %x, %p)\n", This, iface, debugstr_guid(propid), flags, punk);
4996 return E_NOTIMPL;
4997}
4998
5000{
5002
5003 FIXME("(%p/%p)->(%s)\n", This, iface, debugstr_guid(propid));
5004 return E_NOTIMPL;
5005}
5006
5008{
5010
5011 FIXME("(%p/%p)->(%s, %p, %p)\n", This, iface, debugstr_guid(propid), flags, punk);
5012 return E_NOTIMPL;
5013}
5014
5016{
5018
5019 FIXME("(%p/%p)->(%p)\n", This, iface, props);
5020 return E_NOTIMPL;
5021}
5022
5024{
5026 FIXME("(%p/%p)\n", This, iface);
5027}
5028
5030{
5032 FIXME("(%p/%p)\n", This, iface);
5033}
5034
5036{
5038 FIXME("(%p/%p)\n", This, iface);
5039}
5040
5042{
5044 FIXME("(%p/%p)\n", This, iface);
5045}
5046
5048{
5050 FIXME("(%p/%p)\n", This, iface);
5051}
5052
5054{
5056 FIXME("(%p/%p)\n", This, iface);
5057}
5058
5060{
5062 FIXME("(%p/%p)\n", This, iface);
5063}
5064
5065static const IObjContextVtbl Context_Object_Vtbl =
5066{
5081};
5082
5083/***********************************************************************
5084 * CoGetObjectContext [OLE32.@]
5085 *
5086 * Retrieves an object associated with the current context (i.e. apartment).
5087 *
5088 * PARAMS
5089 * riid [I] ID of the interface of the object to retrieve.
5090 * ppv [O] Address where object will be stored on return.
5091 *
5092 * RETURNS
5093 * Success: S_OK.
5094 * Failure: HRESULT code.
5095 */
5097{
5099 HRESULT hr;
5100
5101 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
5102
5103 *ppv = NULL;
5105 if (FAILED(hr))
5106 return hr;
5107
5108 return IObjContext_QueryInterface(context, riid, ppv);
5109}
5110
5111/***********************************************************************
5112 * CoGetContextToken [OLE32.@]
5113 */
5115{
5116 struct oletls *info = COM_CurrentInfo();
5117 APARTMENT *apt;
5118
5119 TRACE("(%p)\n", token);
5120
5121 if (!info)
5122 return E_OUTOFMEMORY;
5123
5125 {
5126 ERR("apartment not initialised\n");
5127 return CO_E_NOTINITIALIZED;
5128 }
5130
5131 if (!token)
5132 return E_POINTER;
5133
5134 if (!info->context_token)
5135 {
5137
5138 context = HeapAlloc(GetProcessHeap(), 0, sizeof(*context));
5139 if (!context)
5140 return E_OUTOFMEMORY;
5141
5142 context->IComThreadingInfo_iface.lpVtbl = &Context_Threading_Vtbl;
5143 context->IContextCallback_iface.lpVtbl = &Context_Callback_Vtbl;
5144 context->IObjContext_iface.lpVtbl = &Context_Object_Vtbl;
5145 /* Context token does not take a reference, it's always zero until the
5146 interface is explicitly requested with CoGetObjectContext(). */
5147 context->refs = 0;
5148
5149 info->context_token = &context->IObjContext_iface;
5150 }
5151
5152 *token = (ULONG_PTR)info->context_token;
5153 TRACE("context_token=%p\n", info->context_token);
5154
5155 return S_OK;
5156}
5157
5158/***********************************************************************
5159 * CoGetDefaultContext [OLE32.@]
5160 */
5162{
5163 FIXME("%d %s %p stub\n", type, debugstr_guid(riid), ppv);
5164 return E_NOINTERFACE;
5165}
5166
5168{
5169 static const WCHAR wszInprocHandler32[] = {'I','n','p','r','o','c','H','a','n','d','l','e','r','3','2',0};
5170 HKEY hkey;
5171 HRESULT hres;
5172
5173 hres = COM_OpenKeyForCLSID(rclsid, wszInprocHandler32, KEY_READ, &hkey);
5174 if (SUCCEEDED(hres))
5175 {
5176 struct class_reg_data regdata;
5178
5179 regdata.u.hkey = hkey;
5180 regdata.hkey = TRUE;
5181
5183 {
5184 static const WCHAR wszOle32[] = {'o','l','e','3','2','.','d','l','l',0};
5185 if (!wcsicmp(dllpath, wszOle32))
5186 {
5188 return HandlerCF_Create(rclsid, riid, ppv);
5189 }
5190 }
5191 else
5192 WARN("not creating object for inproc handler path %s\n", debugstr_w(dllpath));
5194 }
5195
5197}
5198
5199/***********************************************************************
5200 * CoGetApartmentType [OLE32.@]
5201 */
5203{
5204 struct oletls *info = COM_CurrentInfo();
5205 APARTMENT *apt;
5206
5207 TRACE("(%p, %p)\n", type, qualifier);
5208
5209 if (!type || !qualifier)
5210 return E_INVALIDARG;
5211
5212 if (!info)
5213 return E_OUTOFMEMORY;
5214
5215 if (!info->apt)
5216 *type = APTTYPE_CURRENT;
5217 else if (info->apt->multi_threaded)
5218 *type = APTTYPE_MTA;
5219 else if (info->apt->main)
5221 else
5222 *type = APTTYPE_STA;
5223
5225
5226 if (!info->apt && (apt = apartment_find_mta()))
5227 {
5229 *type = APTTYPE_MTA;
5231 }
5232
5233 return info->apt ? S_OK : CO_E_NOTINITIALIZED;
5234}
5235
5236/***********************************************************************
5237 * CoDisableCallCancellation [OLE32.@]
5238 */
5240{
5241 FIXME("(%p): stub\n", reserved);
5242
5243 return E_NOTIMPL;
5244}
5245
5246/***********************************************************************
5247 * CoEnableCallCancellation [OLE32.@]
5248 */
5250{
5251 FIXME("(%p): stub\n", reserved);
5252
5253 return E_NOTIMPL;
5254}
5255
5256/***********************************************************************
5257 * CoRegisterSurrogate [OLE32.@]
5258 */
5260{
5261 FIXME("(%p): stub\n", surrogate);
5262
5263 return E_NOTIMPL;
5264}
5265
5266/***********************************************************************
5267 * CoRegisterSurrogateEx [OLE32.@]
5268 */
5270{
5271 FIXME("(%s %p): stub\n", debugstr_guid(guid), reserved);
5272
5273 return E_NOTIMPL;
5274}
5275
5276typedef struct {
5280
5282{
5283 return CONTAINING_RECORD(iface, GlobalOptions, IGlobalOptions_iface);
5284}
5285
5287{
5289
5290 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
5291
5292 if (IsEqualGUID(&IID_IGlobalOptions, riid) || IsEqualGUID(&IID_IUnknown, riid))
5293 {
5294 *ppv = iface;
5295 }
5296 else
5297 {
5298 *ppv = NULL;
5299 return E_NOINTERFACE;
5300 }
5301
5302 IUnknown_AddRef((IUnknown*)*ppv);
5303 return S_OK;
5304}
5305
5307{
5310
5311 TRACE("(%p) ref=%d\n", This, ref);
5312
5313 return ref;
5314}
5315
5317{
5320
5321 TRACE("(%p) ref=%d\n", This, ref);
5322
5323 if (!ref)
5324 heap_free(This);
5325
5326 return ref;
5327}
5328
5330{
5332 FIXME("(%p)->(%u %lx)\n", This, property, value);
5333 return S_OK;
5334}
5335
5337{
5339 FIXME("(%p)->(%u %p)\n", This, property, value);
5340 return E_NOTIMPL;
5341}
5342
5343static const IGlobalOptionsVtbl GlobalOptionsVtbl = {
5349};
5350
5352{
5354 HRESULT hres;
5355
5356 TRACE("(%p %s %p)\n", outer, debugstr_guid(riid), ppv);
5357
5358 if (outer)
5359 return E_INVALIDARG;
5360
5362 if (!global_options)
5363 return E_OUTOFMEMORY;
5364 global_options->IGlobalOptions_iface.lpVtbl = &GlobalOptionsVtbl;
5365 global_options->ref = 1;
5366
5367 hres = IGlobalOptions_QueryInterface(&global_options->IGlobalOptions_iface, riid, ppv);
5368 IGlobalOptions_Release(&global_options->IGlobalOptions_iface);
5369 return hres;
5370}
5371
5372/***********************************************************************
5373 * DllMain (OLE32.@)
5374 */
5376{
5377 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, reserved);
5378
5379 switch(fdwReason) {
5380 case DLL_PROCESS_ATTACH:
5381 hProxyDll = hinstDLL;
5382 break;
5383
5384 case DLL_PROCESS_DETACH:
5385 if (reserved) break;
5387 if(apt_win_class)
5388 UnregisterClassW( (const WCHAR*)MAKEINTATOM(apt_win_class), hProxyDll );
5393 break;
5394
5395 case DLL_THREAD_DETACH:
5397 break;
5398 }
5399 return TRUE;
5400}
5401
5402/***********************************************************************
5403 * DllRegisterServer (OLE32.@)
5404 */
5406{
5407 return OLE32_DllRegisterServer();
5408}
5409
5410/***********************************************************************
5411 * DllUnregisterServer (OLE32.@)
5412 */
5414{
5416}
#define CO_E_NOTINITIALIZED
static struct _test_info results[8]
Definition: SetCursorPos.c:31
#define DECLSPEC_HOTPATCH
Definition: _mingw.h:240
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define stat
Definition: acwin.h:99
static const struct optioninfo global_options[]
Definition: adh-opts.c:43
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define msg(x)
Definition: auth_time.c:54
static const WCHAR dllW[]
Definition: axinstall.c:36
HWND hWnd
Definition: settings.c:17
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
const WCHAR * alias
Definition: main.c:67
LONG NTSTATUS
Definition: precomp.h:26
static const WCHAR nameW[]
Definition: main.c:49
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
HRESULT WINAPI DllCanUnloadNow(void)
Definition: misc.cpp:160
const GUID IID_IUnknown
const GUID IID_IClassFactory
#define RegCloseKey(hKey)
Definition: registry.h:49
const CLSID CLSID_GlobalOptions
const CLSID CLSID_ManualResetEvent
const CLSID CLSID_InProcFreeMarshaler
const CLSID CLSID_StdGlobalInterfaceTable
Definition: list.h:37
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
static APARTMENT * COM_CurrentApt(void)
#define DEBUG_SET_CRITSEC_NAME(cs, name)
#define WINE_CLSCTX_DONT_HOST
ULONG stub_manager_int_release(struct stub_manager *This) DECLSPEC_HIDDEN
Definition: stubmanager.c:311
void RPC_UnregisterAllChannelHooks(void) DECLSPEC_HIDDEN
Definition: rpc.c:445
HRESULT WINAPI RunningObjectTableImpl_Initialize(void) DECLSPEC_HIDDEN
Definition: moniker.c:979
static struct oletls * COM_CurrentInfo(void)
#define DM_EXECUTERPC
HRESULT RPC_RegisterChannelHook(REFGUID rguid, IChannelHook *hook) DECLSPEC_HIDDEN
Definition: rpc.c:424
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak) DECLSPEC_HIDDEN
Definition: stubmanager.c:408
static GUID COM_CurrentCausalityId(void)
HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) DECLSPEC_HIDDEN
Definition: rpc.c:1804
#define DEBUG_CLEAR_CRITSEC_NAME(cs)
void stub_manager_disconnect(struct stub_manager *m) DECLSPEC_HIDDEN
Definition: stubmanager.c:244
IGlobalInterfaceTable * get_std_git(void) DECLSPEC_HIDDEN
Definition: git.c:362
HRESULT apartment_disconnectproxies(struct apartment *apt) DECLSPEC_HIDDEN
Definition: marshal.c:1226
void release_std_git(void) DECLSPEC_HIDDEN
Definition: git.c:386
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases) DECLSPEC_HIDDEN
Definition: stubmanager.c:439
void RPC_StopLocalServer(void *registration) DECLSPEC_HIDDEN
Definition: rpc.c:2044
#define DM_HOSTOBJECT
HRESULT WINAPI OLE32_DllUnregisterServer(void) DECLSPEC_HIDDEN
HRESULT FTMarshalCF_Create(REFIID riid, LPVOID *ppv) DECLSPEC_HIDDEN
Definition: ftmarshal.c:411
HRESULT HandlerCF_Create(REFCLSID rclsid, REFIID riid, LPVOID *ppv) DECLSPEC_HIDDEN
struct stub_manager * get_stub_manager_from_object(APARTMENT *apt, IUnknown *object, BOOL alloc) DECLSPEC_HIDDEN
Definition: stubmanager.c:337
HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void) DECLSPEC_HIDDEN
Definition: moniker.c:1007
void RPC_ExecuteCall(struct dispatch_params *params) DECLSPEC_HIDDEN
Definition: rpc.c:1327
HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration) DECLSPEC_HIDDEN
Definition: rpc.c:1996
HRESULT WINAPI OLE32_DllRegisterServer(void) DECLSPEC_HIDDEN
#define CHARS_IN_GUID
HMODULE hLibrary
Definition: odbccp32.c:12
#define WM_DDE_FIRST
Definition: dde.h:47
#define WM_DDE_LAST
Definition: dde.h:46
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define ERROR_SUCCESS
Definition: deptool.c:10
static const WCHAR clsidW[]
WORD ATOM
Definition: dimm.idl:113
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG WINAPI RegDeleteKeyW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey)
Definition: reg.c:1239
LSTATUS WINAPI RegQueryValueW(HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count)
Definition: reg.c:4241
LONG WINAPI RegSetValueW(HKEY hKeyOriginal, LPCWSTR lpSubKey, DWORD dwType, LPCWSTR lpData, DWORD cbData)
Definition: reg.c:5000
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define DLL_THREAD_DETACH
Definition: compat.h:133
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
#define DLL_PROCESS_DETACH
Definition: compat.h:130
#define GetProcAddress(x, y)
Definition: compat.h:753
#define HeapAlloc
Definition: compat.h:733
WCHAR OLECHAR
Definition: compat.h:2292
#define FreeLibrary(x)
Definition: compat.h:748
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define GetCurrentProcess()
Definition: compat.h:759
#define IsWow64Process
Definition: compat.h:760
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define CALLBACK
Definition: compat.h:35
#define lstrcpyW
Definition: compat.h:749
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define wcsicmp
Definition: compat.h:15
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static DWORD DWORD * dwLength
Definition: fusion.c:86
VOID WINAPI ReleaseActCtx(IN HANDLE hActCtx)
Definition: actctx.c:208
BOOL WINAPI DeactivateActCtx(IN DWORD dwFlags, IN ULONG_PTR ulCookie)
Definition: actctx.c:268
BOOL WINAPI ActivateActCtx(IN HANDLE hActCtx, OUT PULONG_PTR ulCookie)
Definition: actctx.c:237
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Definition: loader.c:288
DWORD WINAPI SearchPathW(IN LPCWSTR lpPath OPTIONAL, IN LPCWSTR lpFileName, IN LPCWSTR lpExtension OPTIONAL, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart OPTIONAL)
Definition: path.c:1298
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
VOID WINAPI GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime)
Definition: time.c:128
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
BOOL WINAPI InitOnceExecuteOnce(_Inout_ PINIT_ONCE InitOnce, _In_ __callback PINIT_ONCE_FN InitFn, _Inout_opt_ PVOID Parameter, _Outptr_opt_result_maybenull_ LPVOID *Context)
Definition: InitOnce.c:12
BOOL WINAPI FindActCtxSectionStringW(DWORD dwFlags, const GUID *lpExtGuid, ULONG ulId, LPCWSTR lpSearchStr, PACTCTX_SECTION_KEYED_DATA pInfo)
Definition: actctx.c:238
BOOL WINAPI FindActCtxSectionGuid(DWORD dwFlags, const GUID *lpExtGuid, ULONG ulId, const GUID *lpSearchGuid, PACTCTX_SECTION_KEYED_DATA pInfo)
Definition: actctx.c:265
BOOL is_wow64
Definition: msi.c:52
HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
Definition: compobj.c:2690
static APARTMENT * apartment_findmain(void)
Definition: compobj.c:1324
DWORD WINAPI CoGetCurrentProcess(void)
Definition: compobj.c:4004
static BOOL get_object_dll_path(const struct class_reg_data *regdata, WCHAR *dst, DWORD dstlen)
Definition: compobj.c:1413
static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay)
Definition: compobj.c:1132
static HRESULT COM_GetRegisteredClassObject(const struct apartment *apt, REFCLSID rclsid, DWORD dwClsContext, LPUNKNOWN *ppUnk)
Definition: compobj.c:2832
void WINAPI CoFreeLibrary(HINSTANCE hLibrary)
Definition: compobj.c:3638
static APARTMENT * apartment_find_mta(void)
Definition: compobj.c:726
HRESULT WINAPI CoRegisterClassObject(REFCLSID rclsid, LPUNKNOWN pUnk, DWORD dwClsContext, DWORD flags, LPDWORD lpdwRegister)
Definition: compobj.c:2897
static BOOL is_valid_hex(WCHAR c)
Definition: compobj.c:2217
static void COM_RevokeAllClasses(const struct apartment *apt)
Definition: compobj.c:764
static HRESULT WINAPI Context_CTI_GetCurrentLogicalThreadId(IComThreadingInfo *iface, GUID *logical_thread_id)
Definition: compobj.c:4915
ULONG WINAPI CoAddRefServerProcess(void)
Definition: compobj.c:4162
HRESULT(WINAPI * DllCanUnloadNowFunc)(void)
Definition: compobj.c:450
HRESULT WINAPI CoRegisterMessageFilter(LPMESSAGEFILTER lpMessageFilter, LPMESSAGEFILTER *lplpMessageFilter)
Definition: compobj.c:4046
static const IServiceProviderVtbl LocalServerVtbl
Definition: compobj.c:1018
static ULONG WINAPI GlobalOptions_AddRef(IGlobalOptions *iface)
Definition: compobj.c:5306
HRESULT apartment_createwindowifneeded(struct apartment *apt)
Definition: compobj.c:1704
static Context * impl_from_IComThreadingInfo(IComThreadingInfo *iface)
Definition: compobj.c:4802
void WINAPI DECLSPEC_HOTPATCH CoFreeUnusedLibrariesEx(DWORD dwUnloadDelay, DWORD dwReserved)
Definition: compobj.c:3677
comclass_miscfields
Definition: compobj.c:99
@ MiscStatusContent
Definition: compobj.c:102
@ MiscStatusThumbnail
Definition: compobj.c:103
@ MiscStatus
Definition: compobj.c:100
@ MiscStatusDocPrint
Definition: compobj.c:104
@ MiscStatusIcon
Definition: compobj.c:101
static HRESULT WINAPI ISynchronize_fnReset(ISynchronize *iface)
Definition: compobj.c:870
HRESULT WINAPI CoGetObject(LPCWSTR pszName, BIND_OPTS *pBindOptions, REFIID riid, void **ppv)
Definition: compobj.c:4742
static ISynchronizeVtbl vt_ISynchronize
Definition: compobj.c:878
static const WCHAR classes_rootW[]
Definition: compobj.c:344
HRESULT WINAPI CoGetInstanceFromIStorage(COSERVERINFO *server_info, CLSID *rclsid, IUnknown *outer, DWORD cls_context, IStorage *storage, DWORD count, MULTI_QI *results)
Definition: compobj.c:3541
static void WINAPI Context_OC_Reserved4(IObjContext *iface)
Definition: compobj.c:5041
HRESULT WINAPI CoFileTimeNow(FILETIME *lpFileTime)
Definition: compobj.c:3717
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
static void init_multi_qi(DWORD count, MULTI_QI *mqi, HRESULT hr)
Definition: compobj.c:3346
HRESULT WINAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID clsidNew)
Definition: compobj.c:3959
static MREImpl * impl_from_ISynchronize(ISynchronize *iface)
Definition: compobj.c:805
static ATOM apt_win_class
Definition: compobj.c:483
HRESULT WINAPI DllRegisterServer(void)
Definition: compobj.c:5405
static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath, BOOL apartment_threaded, REFCLSID rclsid, REFIID riid, void **ppv)
Definition: compobj.c:1340
static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: compobj.c:1498
static APARTMENT * MTA
Definition: compobj.c:76
HRESULT WINAPI CoRegisterSurrogate(ISurrogate *surrogate)
Definition: compobj.c:5259
HRESULT WINAPI IIDFromString(LPCOLESTR s, IID *iid)
Definition: compobj.c:2374
static ULONG WINAPI Context_CTI_AddRef(IComThreadingInfo *iface)
Definition: compobj.c:4869
static HRESULT WINAPI Context_CTI_SetCurrentLogicalThreadId(IComThreadingInfo *iface, REFGUID logical_thread_id)
Definition: compobj.c:4921
static Context * impl_from_IContextCallback(IContextCallback *iface)
Definition: compobj.c:4807
struct ManualResetEvent MREImpl
static APARTMENT * apartment_get_or_create(DWORD model)
Definition: compobj.c:670
static DWORD apartment_addref(struct apartment *apt)
Definition: compobj.c:619
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID reserved)
Definition: compobj.c:5375
static ULONG Context_AddRef(Context *This)
Definition: compobj.c:4845
static ULONG WINAPI ISynchronize_fnRelease(ISynchronize *iface)
Definition: compobj.c:839
static HRESULT get_local_server_stream(APARTMENT *apt, IStream **ret)
Definition: compobj.c:1025
static CRITICAL_SECTION_DEBUG class_cs_debug
Definition: compobj.c:229
static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret)
Definition: compobj.c:508
DWORD WINAPI CoBuildVersion(void)
Definition: compobj.c:1774
static ULONG WINAPI Context_OC_AddRef(IObjContext *iface)
Definition: compobj.c:4979
HRESULT COM_OpenKeyForCLSID(REFCLSID clsid, LPCWSTR keyname, REGSAM access, HKEY *subkey)
Definition: compobj.c:2448
static HRESULT WINAPI LocalServer_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
Definition: compobj.c:948
static struct list registered_psclsid_list
Definition: compobj.c:172
static LocalServer * impl_from_IServiceProvider(IServiceProvider *iface)
Definition: compobj.c:943
static HRESULT WINAPI Context_CC_QueryInterface(IContextCallback *iface, REFIID riid, LPVOID *ppv)
Definition: compobj.c:4938
BOOL WINAPI CoIsOle1Class(REFCLSID clsid)
Definition: compobj.c:4093
static HRESULT Context_QueryInterface(Context *iface, REFIID riid, LPVOID *ppv)
Definition: compobj.c:4817
static HRESULT WINAPI SynchronizeHandle_QueryInterface(ISynchronizeHandle *iface, REFIID riid, void **ppv)
Definition: compobj.c:892
HRESULT WINAPI CoSetState(IUnknown *pv)
Definition: compobj.c:3851
static const IComThreadingInfoVtbl Context_Threading_Vtbl
Definition: compobj.c:4927
static void COM_RevokeRegisteredClassObject(RegisteredClass *curClass)
Definition: compobj.c:753
static ULONG WINAPI ISynchronize_fnAddRef(ISynchronize *iface)
Definition: compobj.c:830
static ULONG WINAPI GlobalOptions_Release(IGlobalOptions *iface)
Definition: compobj.c:5316
static HRESULT WINAPI Context_CTI_QueryInterface(IComThreadingInfo *iface, REFIID riid, LPVOID *ppv)
Definition: compobj.c:4863
static HKEY classes_root_hkey
Definition: compobj.c:349
static HRESULT return_multi_qi(IUnknown *unk, DWORD count, MULTI_QI *mqi, BOOL include_unk)
Definition: compobj.c:3357
static void lock_init_spies(struct oletls *info)
Definition: compobj.c:1797
static void COM_TlsDestroy(void)
Definition: compobj.c:1739
HRESULT WINAPI CoRegisterInitializeSpy(IInitializeSpy *spy, ULARGE_INTEGER *cookie)
Definition: compobj.c:1832
BOOL WINAPI CoIsHandlerConnected(IUnknown *pUnk)
Definition: compobj.c:4223
static MREImpl * impl_from_ISynchronizeHandle(ISynchronizeHandle *iface)
Definition: compobj.c:887
HRESULT WINAPI CoDisconnectObject(LPUNKNOWN lpUnk, DWORD reserved)
Definition: compobj.c:2149
HRESULT WINAPI CoInitializeWOW(DWORD x, DWORD y)
Definition: compobj.c:3793
static HRESULT get_ps_clsid_from_registry(const WCHAR *path, REGSAM access, CLSID *pclsid)
Definition: compobj.c:2632
static GlobalOptions * impl_from_IGlobalOptions(IGlobalOptions *iface)
Definition: compobj.c:5281
static struct list openDllList
Definition: compobj.c:462
static APARTMENT * apartment_construct(DWORD model)
Definition: compobj.c:628
DWORD apartment_release(struct apartment *apt)
Definition: compobj.c:1172
static CRITICAL_SECTION_DEBUG critsect_debug
Definition: compobj.c:81
HRESULT COM_OpenKeyForAppIdFromCLSID(REFCLSID clsid, REGSAM access, HKEY *subkey)
Definition: compobj.c:2480
HRESULT WINAPI CoCopyProxy(IUnknown *pProxy, IUnknown **ppCopy)
Definition: compobj.c:4346
static HRESULT WINAPI Context_OC_GetProperty(IObjContext *iface, REFGUID propid, CPFLAGS *flags, IUnknown **punk)
Definition: compobj.c:5007
HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree)
Definition: compobj.c:3617
static const IGlobalOptionsVtbl GlobalOptionsVtbl
Definition: compobj.c:5343
static struct init_spy * get_spy_entry(struct oletls *info, unsigned int id)
Definition: compobj.c:1780
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstanceEx(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, COSERVERINFO *pServerInfo, ULONG cmq, MULTI_QI *pResults)
Definition: compobj.c:3387
HRESULT WINAPI CoDisableCallCancellation(void *reserved)
Definition: compobj.c:5239
HRESULT WINAPI CoGetContextToken(ULONG_PTR *token)
Definition: compobj.c:5114
void WINAPI CoFreeAllLibraries(void)
Definition: compobj.c:3655
HRESULT WINAPI CoWaitForMultipleHandles(DWORD dwFlags, DWORD dwTimeout, ULONG cHandles, LPHANDLE pHandles, LPDWORD lpdwindex)
Definition: compobj.c:4578
HRESULT WINAPI CoEnableCallCancellation(void *reserved)
Definition: compobj.c:5249
HRESULT WINAPI DECLSPEC_HOTPATCH CoRevokeClassObject(DWORD dwRegister)
Definition: compobj.c:1086
static ULONG WINAPI Context_OC_Release(IObjContext *iface)
Definition: compobj.c:4985
static void WINAPI Context_OC_Reserved6(IObjContext *iface)
Definition: compobj.c:5053
HRESULT(CALLBACK * DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv)
Definition: compobj.c:449
static HRESULT WINAPI Context_CC_ContextCallback(IContextCallback *iface, PFNCONTEXTCALL pCallback, ComCallData *param, REFIID riid, int method, IUnknown *punk)
Definition: compobj.c:4956
HRESULT WINAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew)
Definition: compobj.c:3886
static ULONG WINAPI LocalServer_AddRef(IServiceProvider *iface)
Definition: compobj.c:965
static HRESULT get_inproc_class_object(APARTMENT *apt, const struct class_reg_data *regdata, REFCLSID rclsid, REFIID riid, BOOL hostifnecessary, void **ppv)
Definition: compobj.c:3026
HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
Definition: compobj.c:2002
static CRITICAL_SECTION csOpenDllList
Definition: compobj.c:464
HRESULT WINAPI CoCreateGuid(GUID *pguid)
Definition: compobj.c:2206
static void revoke_registered_psclsids(void)
Definition: compobj.c:779
static void COMPOBJ_DllList_Free(void)
Definition: compobj.c:600
static HKEY get_classes_root_hkey(HKEY hkey, REGSAM access)
Definition: compobj.c:381
static BOOL COM_PeekMessage(struct apartment *apt, MSG *msg)
Definition: compobj.c:4544
HRESULT WINAPI DllUnregisterServer(void)
Definition: compobj.c:5413
APARTMENT * apartment_findfromoxid(OXID oxid, BOOL ref)
Definition: compobj.c:1276
static APARTMENT * MainApartment
Definition: compobj.c:77
static HRESULT WINAPI GlobalOptions_Set(IGlobalOptions *iface, GLOBALOPT_PROPERTIES property, ULONG_PTR value)
Definition: compobj.c:5329
BOOL actctx_get_miscstatus(const CLSID *clsid, DWORD aspect, DWORD *status)
Definition: compobj.c:254
static BOOL apartment_is_model(const APARTMENT *apt, DWORD model)
Definition: compobj.c:718
static HKEY create_classes_root_hkey(DWORD access)
Definition: compobj.c:352
static HRESULT WINAPI Context_CTI_GetCurrentApartmentType(IComThreadingInfo *iface, APTTYPE *apttype)
Definition: compobj.c:4881
static ULONG WINAPI SynchronizeHandle_AddRef(ISynchronizeHandle *iface)
Definition: compobj.c:898
void WINAPI DECLSPEC_HOTPATCH CoFreeUnusedLibraries(void)
Definition: compobj.c:3701
static HRESULT WINAPI GlobalOptions_QueryInterface(IGlobalOptions *iface, REFIID riid, void **ppv)
Definition: compobj.c:5286
HRESULT WINAPI CoSwitchCallContext(IUnknown *pObject, IUnknown **ppOldObject)
Definition: compobj.c:4408
HRESULT WINAPI DECLSPEC_HOTPATCH CLSIDFromProgID(LPCOLESTR progid, LPCLSID clsid)
Definition: compobj.c:2602
HRESULT WINAPI CoGetCallContext(REFIID riid, void **ppv)
Definition: compobj.c:4379
static ULONG WINAPI Context_CTI_Release(IComThreadingInfo *iface)
Definition: compobj.c:4875
HRESULT WINAPI CoQueryClientBlanket(DWORD *pAuthnSvc, DWORD *pAuthzSvc, OLECHAR **pServerPrincName, DWORD *pAuthnLevel, DWORD *pImpLevel, RPC_AUTHZ_HANDLE *pPrivs, DWORD *pCapabilities)
Definition: compobj.c:4445
HRESULT WINAPI CoGetObjectContext(REFIID riid, void **ppv)
Definition: compobj.c:5096
HRESULT WINAPI CoGetState(IUnknown **ppv)
Definition: compobj.c:3819
HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier)
Definition: compobj.c:5202
HRESULT Handler_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
Definition: compobj.c:5167
static HRESULT WINAPI Context_CTI_GetCurrentThreadType(IComThreadingInfo *iface, THDTYPE *thdtype)
Definition: compobj.c:4890
HRESULT WINAPI CoSetProxyBlanket(IUnknown *pProxy, DWORD AuthnSvc, DWORD AuthzSvc, OLECHAR *pServerPrincName, DWORD AuthnLevel, DWORD ImpLevel, void *pAuthInfo, DWORD Capabilities)
Definition: compobj.c:4307
static void WINAPI Context_OC_Reserved7(IObjContext *iface)
Definition: compobj.c:5059
static CRITICAL_SECTION_DEBUG psclsid_cs_debug
Definition: compobj.c:175
static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry, BOOL free_entry)
Definition: compobj.c:583
HRESULT WINAPI CoSuspendClassObjects(void)
Definition: compobj.c:4144
APARTMENT * apartment_findfromtid(DWORD tid)
Definition: compobj.c:1300
static HRESULT ManualResetEvent_Construct(IUnknown *punkouter, REFIID iid, void **ppv)
Definition: compobj.c:925
HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3103
static LONG s_COMLockCount
Definition: compobj.c:202
static void WINAPI Context_OC_Reserved3(IObjContext *iface)
Definition: compobj.c:5035
HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid)
Definition: compobj.c:2778
static NTSTATUS create_key(HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr)
Definition: compobj.c:303
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
HRESULT WINAPI CoResumeClassObjects(void)
Definition: compobj.c:3288
static CRITICAL_SECTION cs_registered_psclsid_list
Definition: compobj.c:174
void leave_apartment(struct oletls *info)
Definition: compobj.c:1937
static HRESULT WINAPI ISynchronize_fnQueryInterface(ISynchronize *iface, REFIID riid, void **ppv)
Definition: compobj.c:810
HRESULT enter_apartment(struct oletls *info, DWORD model)
Definition: compobj.c:1913
struct tagOpenDll OpenDll
static const ISynchronizeHandleVtbl SynchronizeHandleVtbl
Definition: compobj.c:918
HRESULT WINAPI CoImpersonateClient(void)
Definition: compobj.c:4494
static ULONG WINAPI LocalServer_Release(IServiceProvider *iface)
Definition: compobj.c:975
static ULONG WINAPI SynchronizeHandle_Release(ISynchronizeHandle *iface)
Definition: compobj.c:904
static DWORD CALLBACK apartment_hostobject_thread(LPVOID p)
Definition: compobj.c:1521
static HRESULT WINAPI Context_OC_QueryInterface(IObjContext *iface, REFIID riid, LPVOID *ppv)
Definition: compobj.c:4973
HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id)
Definition: compobj.c:2338
static void WINAPI Context_OC_Reserved5(IObjContext *iface)
Definition: compobj.c:5047
APARTMENT * apartment_get_current_or_mta(void)
Definition: compobj.c:742
HWND apartment_getwindow(const struct apartment *apt)
Definition: compobj.c:1733
LSTATUS create_classes_key(HKEY hkey, const WCHAR *name, REGSAM access, HKEY *retkey)
Definition: compobj.c:402
static CRITICAL_SECTION csApartment
Definition: compobj.c:80
static HRESULT WINAPI LocalServer_QueryService(IServiceProvider *iface, REFGUID guid, REFIID riid, void **ppv)
Definition: compobj.c:990
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
struct tagRegisteredClass RegisteredClass
static HRESULT apartment_hostobject(struct apartment *apt, const struct host_object_params *params)
Definition: compobj.c:1468
HRESULT WINAPI CLSIDFromProgIDEx(LPCOLESTR progid, LPCLSID clsid)
Definition: compobj.c:2625
HRESULT WINAPI CoRegisterSurrogateEx(REFGUID guid, void *reserved)
Definition: compobj.c:5269
static struct list RegisteredClassList
Definition: compobj.c:226
static ULONG Context_Release(Context *This)
Definition: compobj.c:4850
HRESULT WINAPI CoRegisterChannelHook(REFGUID guidExtension, IChannelHook *pChannelHook)
Definition: compobj.c:4787
HRESULT WINAPI DECLSPEC_HOTPATCH CoGetInstanceFromFile(COSERVERINFO *server_info, CLSID *rclsid, IUnknown *outer, DWORD cls_context, DWORD grfmode, OLECHAR *filename, DWORD count, MULTI_QI *results)
Definition: compobj.c:3468
HRESULT WINAPI CoRevertToSelf(void)
Definition: compobj.c:4527
ULONG WINAPI CoReleaseServerProcess(void)
Definition: compobj.c:4193
static const IContextCallbackVtbl Context_Callback_Vtbl
Definition: compobj.c:4965
static BOOL guid_from_string(LPCWSTR s, GUID *id)
Definition: compobj.c:2238
static HRESULT WINAPI Context_OC_RemoveProperty(IObjContext *iface, REFGUID propid)
Definition: compobj.c:4999
LSTATUS open_classes_key(HKEY hkey, const WCHAR *name, REGSAM access, HKEY *retkey)
Definition: compobj.c:420
static void unlock_init_spies(struct oletls *info)
Definition: compobj.c:1802
static ULONG WINAPI Context_CC_AddRef(IContextCallback *iface)
Definition: compobj.c:4944
HRESULT WINAPI CoQueryProxyBlanket(IUnknown *pProxy, DWORD *pAuthnSvc, DWORD *pAuthzSvc, OLECHAR **ppServerPrincName, DWORD *pAuthnLevel, DWORD *pImpLevel, void **ppAuthInfo, DWORD *pCapabilities)
Definition: compobj.c:4262
HRESULT WINAPI CoLockObjectExternal(LPUNKNOWN pUnk, BOOL fLock, BOOL fLastUnlockReleases)
Definition: compobj.c:3743
static struct list apts
Definition: compobj.c:78
HRESULT WINAPI CoGetDefaultContext(APTTYPE type, REFIID riid, LPVOID *ppv)
Definition: compobj.c:5161
HRESULT WINAPI CoInitializeSecurity(PSECURITY_DESCRIPTOR pSecDesc, LONG cAuthSvc, SOLE_AUTHENTICATION_SERVICE *asAuthSvc, void *pReserved1, DWORD dwAuthnLevel, DWORD dwImpLevel, void *pReserved2, DWORD dwCapabilities, void *pReserved3)
Definition: compobj.c:4122
HRESULT WINAPI CoRevokeInitializeSpy(ULARGE_INTEGER cookie)
Definition: compobj.c:1891
static const BYTE guid_conv_table[256]
Definition: compobj.c:2226
static HRESULT WINAPI Context_OC_EnumContextProps(IObjContext *iface, IEnumContextProps **props)
Definition: compobj.c:5015
static HRESULT WINAPI GlobalOptions_Query(IGlobalOptions *iface, GLOBALOPT_PROPERTIES property, ULONG_PTR *value)
Definition: compobj.c:5336
static ULONG WINAPI Context_CC_Release(IContextCallback *iface)
Definition: compobj.c:4950
static enum comclass_miscfields dvaspect_to_miscfields(DWORD aspect)
Definition: compobj.c:237
static CRITICAL_SECTION csRegisteredClassList
Definition: compobj.c:228
comclass_threadingmodel
Definition: compobj.c:90
@ ThreadingModel_No
Definition: compobj.c:93
@ ThreadingModel_Both
Definition: compobj.c:94
@ ThreadingModel_Neutral
Definition: compobj.c:95
@ ThreadingModel_Free
Definition: compobj.c:92
@ ThreadingModel_Apartment
Definition: compobj.c:91
HRESULT WINAPI StringFromCLSID(REFCLSID id, LPOLESTR *idstr)
Definition: compobj.c:2412
static const WCHAR wszAptWinClass[]
Definition: compobj.c:481
static void WINAPI Context_OC_Reserved2(IObjContext *iface)
Definition: compobj.c:5029
static HRESULT WINAPI Context_OC_SetProperty(IObjContext *iface, REFGUID propid, CPFLAGS flags, IUnknown *punk)
Definition: compobj.c:4991
HRESULT WINAPI GlobalOptions_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
Definition: compobj.c:5351
static HRESULT WINAPI ISynchronize_fnSignal(ISynchronize *iface)
Definition: compobj.c:862
static HRESULT clsid_from_string_reg(LPCOLESTR progid, CLSID *clsid)
Definition: compobj.c:2290
HRESULT WINAPI DECLSPEC_HOTPATCH ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *ppszProgID)
Definition: compobj.c:2530
static const IObjContextVtbl Context_Object_Vtbl
Definition: compobj.c:5065
HRESULT WINAPI CoGetCurrentLogicalThreadId(GUID *id)
Definition: compobj.c:4012
static Context * impl_from_IObjContext(IObjContext *iface)
Definition: compobj.c:4812
static void WINAPI Context_OC_Reserved1(IObjContext *iface)
Definition: compobj.c:5023
static enum comclass_threadingmodel get_threading_model(const struct class_reg_data *data)
Definition: compobj.c:2997
static CRITICAL_SECTION_DEBUG dll_cs_debug
Definition: compobj.c:465
HRESULT WINAPI CoAllowSetForegroundWindow(IUnknown *pUnk, void *pvReserved)
Definition: compobj.c:4234
static HRESULT WINAPI ISynchronize_fnWait(ISynchronize *iface, DWORD dwFlags, DWORD dwMilliseconds)
Definition: compobj.c:854
static LONG s_COMServerProcessReferences
Definition: compobj.c:204
static HRESULT WINAPI SynchronizeHandle_GetHandle(ISynchronizeHandle *iface, HANDLE *ph)
Definition: compobj.c:910
static OpenDll * COMPOBJ_DllList_Get(LPCWSTR library_name)
Definition: compobj.c:489
INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
Definition: compobj.c:2434
static HRESULT apartment_hostobject_in_hostapt(struct apartment *apt, BOOL multi_threaded, BOOL main_apartment, const struct class_reg_data *regdata, REFCLSID rclsid, REFIID riid, void **ppv)
Definition: compobj.c:1573
HRESULT WINAPI CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm)
HRESULT WINAPI CoReleaseMarshalData(IStream *pStream)
Definition: marshal.c:2055
HRESULT WINAPI CoUnmarshalInterface(IStream *pStream, REFIID riid, LPVOID *ppv)
Definition: marshal.c:1981
HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk, DWORD dwDestContext, void *pvDestContext, DWORD mshlFlags)
Definition: marshal.c:1876
HRESULT WINAPI GetClassFile(LPCOLESTR filePathName, CLSID *pclsid)
Definition: moniker.c:1213
HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName, LPDWORD pchEaten, LPMONIKER *ppmk)
Definition: moniker.c:1129
static const BOOL is_win64
Definition: shellpath.c:59
#define swprintf
Definition: precomp.h:40
#define assert(x)
Definition: debug.h:53
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
method
Definition: dragdrop.c:54
r reserved
Definition: btrfs.c:3006
#define INFINITE
Definition: serial.h:102
#define ULONG_PTR
Definition: config.h:101
#define progid(str)
Definition: exdisp.idl:31
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
time_t now
Definition: finger.c:65
FxPnpStateCallbackInfo * pCallback
FxObject * pObject
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLenum const GLfloat * params
Definition: glext.h:5645
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLenum dst
Definition: glext.h:6340
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glext.h:7005
GLbitfield flags
Definition: glext.h:7161
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLfloat GLfloat p
Definition: glext.h:8902
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
_Must_inspect_result_ typedef _Out_ PHIDP_CAPS Capabilities
Definition: hidclass.h:103
const char cursor[]
Definition: icontest.c:13
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define InterlockedExchangeAdd
Definition: interlocked.h:181
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
const char * filename
Definition: ioapi.h:137
#define NtCurrentTeb
uint32_t entry
Definition: isohybrid.c:63
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_w
Definition: kernel32.h:32
#define REG_SZ
Definition: layer.c:22
if(dx< 0)
Definition: linetemp.h:194
WCHAR dllpath[MAX_PATH]
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
const GUID * guid
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static PVOID ptr
Definition: dispmode.c:27
static ATOM register_class(void)
Definition: atl_ax.c:49
static LPCSTR DWORD void * pvReserved
Definition: str.c:196
HRESULT hres
Definition: protocol.c:465
static UINT exit_code
Definition: process.c:78
static TfClientId tid
static DWORD dstlen
Definition: directory.c:51
static IUnknown ** ppOldObject
Definition: compobj.c:75
static DWORD dwCoInit
Definition: compobj.c:73
static APTTYPEQUALIFIER * qualifier
Definition: compobj.c:79
UINT64 OXID
Definition: marshal.c:87
static const LARGE_INTEGER llZero
Definition: moniker.c:1113
static LPOLESTR
Definition: stg_prop.c:27
REFCLSID clsid
Definition: msctf.c:82
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED _In_opt_ LPTRANSMIT_FILE_BUFFERS _In_ DWORD dwReserved
Definition: mswsock.h:95
unsigned int UINT
Definition: ndis.h:50
static LPUNKNOWN
Definition: ndr_ole.c:49
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define KEY_WRITE
Definition: nt_native.h:1031
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
NTSTATUS NTAPI NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
Definition: ntapi.c:240
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define L(x)
Definition: ntvdm.h:50
@ REGCLS_MULTI_SEPARATE
Definition: objbase.h:394
@ REGCLS_MULTIPLEUSE
Definition: objbase.h:393
enum tagCOINIT COINIT
@ COWAIT_ALERTABLE
Definition: objbase.h:697
@ COWAIT_WAITALL
Definition: objbase.h:696
@ COINIT_APARTMENTTHREADED
Definition: objbase.h:278
@ COINIT_MULTITHREADED
Definition: objbase.h:279
interface IMessageFilter * LPMESSAGEFILTER
Definition: objfwd.h:14
enum APTTYPE_MAINSTA
enum _THDTYPE THDTYPE
enum APTTYPE_MTA
@ APTTYPEQUALIFIER_IMPLICIT_MTA
Definition: objidl.idl:2332
@ APTTYPEQUALIFIER_NONE
Definition: objidl.idl:2331
enum APTTYPE_STA
DWORD CPFLAGS
Definition: objidl.idl:2476
enum _APTTYPEQUALIFIER APTTYPEQUALIFIER
@ THDTYPE_PROCESSMESSAGES
Definition: objidl.idl:2341
@ THDTYPE_BLOCKMESSAGES
Definition: objidl.idl:2340
#define rup
Definition: ole2ver.h:42
#define rmm
Definition: ole2ver.h:41
HRESULT WINAPI CreateBindCtx(DWORD reserved, LPBC *ppbc)
Definition: bindctx.c:556
const GUID IID_IPersistStorage
const GUID IID_IPersistFile
IClassFactory GlobalOptionsCF
Definition: oleproxy.c:160
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define CLSID_NULL
Definition: guiddef.h:99
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define REFCLSID
Definition: guiddef.h:117
#define IsEqualCLSID(rclsid1, rclsid2)
Definition: guiddef.h:96
static unsigned __int64 next
Definition: rand_nt.c:6
const WCHAR * str
#define RPC_S_OK
Definition: rpcnterr.h:22
RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
Definition: rpcrt4_main.c:305
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:204
#define LIST_FOR_EACH(cursor, list)
Definition: list.h:188
#define LIST_FOR_EACH_SAFE(cursor, cursor2, list)
Definition: list.h:192
#define memset(x, y, z)
Definition: compat.h:39
int zero
Definition: sehframes.cpp:29
HRESULT hr
Definition: shlfolder.c:183
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
Definition: shsvcs.c:38
#define TRACE(s)
Definition: solgame.cpp:4
IComThreadingInfo IComThreadingInfo_iface
Definition: compobj.c:4796
IContextCallback IContextCallback_iface
Definition: compobj.c:4797
LONG refs
Definition: compobj.c:4799
IObjContext IObjContext_iface
Definition: compobj.c:4798
IGlobalOptions IGlobalOptions_iface
Definition: compobj.c:5277
IStream * marshal_stream
Definition: compobj.c:194
IServiceProvider IServiceProvider_iface
Definition: compobj.c:191
LONG ref
Definition: compobj.c:192
APARTMENT * apt
Definition: compobj.c:193
ISynchronize ISynchronize_iface
Definition: compobj.c:799
HANDLE event
Definition: compobj.c:802
ISynchronizeHandle ISynchronizeHandle_iface
Definition: compobj.c:800
COAUTHINFO * pAuthInfo
Definition: objidl.idl:34
LPWSTR pwszName
Definition: objidl.idl:33
LIST_ENTRY ProcessLocksList
Definition: winbase.h:907
Definition: scsiwmi.h:51
LPCWSTR lpszClassName
Definition: winuser.h:3188
HINSTANCE hInstance
Definition: winuser.h:3183
WNDPROC lpfnWndProc
Definition: winuser.h:3180
struct list entry
Definition: compobj.c:475
struct list proxies
struct list entry
struct list loaded_dlls
LPMESSAGEFILTER filter
BOOL being_destroyed
CRITICAL_SECTION cs
DWORD host_apt_tid
BOOL remunk_exported
struct list stubmgrs
HWND host_apt_hwnd
LocalServer * local_server
BOOL multi_threaded
Definition: cookie.c:202
struct comclassredirect_data * data
Definition: compobj.c:156
struct class_reg_data::@524::@525 actctx
HANDLE hactctx
Definition: compobj.c:158
void * section
Definition: compobj.c:157
union class_reg_data::@524 u
DWORD miscstatusdocprint
Definition: compobj.c:128
DWORD miscstatusthumbnail
Definition: compobj.c:126
Definition: http.c:7252
Definition: cookie.c:34
BOOL apartment_threaded
Definition: compobj.c:1465
struct class_reg_data regdata
Definition: compobj.c:1459
IStream * stream
Definition: compobj.c:1464
COINIT threading_model
Definition: compobj.c:1514
HANDLE ready_event
Definition: compobj.c:1515
IInitializeSpy * spy
Definition: copy.c:22
Definition: list.h:15
Definition: name.c:39
struct apartment * apt
Definition: send.c:48
struct list entry
Definition: compobj.c:167
Definition: stat.h:55
Definition: ps.c:97
APARTMENT * apt
LONG refs
Definition: compobj.c:454
DllCanUnloadNowFunc DllCanUnloadNow
Definition: compobj.c:458
HANDLE library
Definition: compobj.c:456
DllGetClassObjectFunc DllGetClassObject
Definition: compobj.c:457
LPWSTR library_name
Definition: compobj.c:455
struct list entry
Definition: compobj.c:459
struct list entry
Definition: compobj.c:216
LPUNKNOWN classObject
Definition: compobj.c:219
void * RpcRegistration
Definition: compobj.c:223
CLSID classIdentifier
Definition: compobj.c:217
DWORD connectFlags
Definition: compobj.c:221
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714
DWORD WINAPI WaitForMultipleObjectsEx(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:169
#define LIST_INIT(head)
Definition: queue.h:197
#define LIST_ENTRY(type)
Definition: queue.h:175
#define DWORD_PTR
Definition: treelist.c:76
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
unsigned char * LPBYTE
Definition: typedefs.h:53
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
static EFI_HANDLE * handles
Definition: uefidisk.c:62
Definition: pdh_main.c:94
static const WCHAR props[]
Definition: wbemdisp.c:288
int ret
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158
#define LOAD_WITH_ALTERED_SEARCH_PATH
Definition: winbase.h:369
#define MAKEINTATOM(i)
Definition: winbase.h:1487
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
RTL_RUN_ONCE INIT_ONCE
Definition: winbase.h:3955
#define WAIT_OBJECT_0
Definition: winbase.h:431
#define WAIT_FAILED
Definition: winbase.h:438
#define INIT_ONCE_STATIC_INIT
Definition: winbase.h:636
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
_In_ void _In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_ DWORD _In_ DWORD dwTimeout
Definition: wincrypt.h:6081
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6
#define REGDB_E_CLASSNOTREG
Definition: winerror.h:2696
#define S_FALSE
Definition: winerror.h:2357
#define CO_E_IIDSTRING
Definition: winerror.h:2807
#define RPC_E_WRONG_THREAD
Definition: winerror.h:2490
#define E_NOINTERFACE
Definition: winerror.h:2364
#define REGDB_E_READREGDB
Definition: winerror.h:2692
#define REGDB_E_IIDNOTREG
Definition: winerror.h:2697
#define REGDB_E_WRITEREGDB
Definition: winerror.h:2693
#define E_ACCESSDENIED
Definition: winerror.h:2849
#define RPC_E_CALL_CANCELED
Definition: winerror.h:2459
#define NOERROR
Definition: winerror.h:2354
#define RPC_S_CALLPENDING
Definition: winerror.h:2497
#define CLASS_E_NOAGGREGATION
Definition: winerror.h:2662
#define RPC_E_CALL_COMPLETE
Definition: winerror.h:2499
#define E_UNEXPECTED
Definition: winerror.h:2456
#define CO_E_DLLNOTFOUND
Definition: winerror.h:2811
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
#define RPC_E_NO_SYNC
Definition: winerror.h:2508
#define RPC_S_UUID_LOCAL_ONLY
Definition: winerror.h:1131
#define CO_S_NOTALLINTERFACES
Definition: winerror.h:2854
#define E_POINTER
Definition: winerror.h:2365
#define CO_E_OBJISREG
Definition: winerror.h:2815
#define CO_E_NOT_SUPPORTED
Definition: winerror.h:2397
#define CLASS_E_CLASSNOTAVAILABLE
Definition: winerror.h:2663
#define REGDB_E_KEYMISSING
Definition: winerror.h:2694
#define RPC_E_CHANGED_MODE
Definition: winerror.h:2482
#define CO_E_CLASSSTRING
Definition: winerror.h:2806
ACCESS_MASK REGSAM
Definition: winreg.h:69
#define HKEY_CLASSES_ROOT
Definition: winreg.h:10
#define HWND_MESSAGE
Definition: winuser.h:1213
#define QS_SENDMESSAGE
Definition: winuser.h:883
#define WM_QUIT
Definition: winuser.h:1626
BOOL WINAPI TranslateMessage(_In_ const MSG *)
#define MWMO_ALERTABLE
Definition: winuser.h:912
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI GetMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT)
__analysis_noreturn void WINAPI PostQuitMessage(_In_ int)
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
#define QS_ALLPOSTMESSAGE
Definition: winuser.h:885
DWORD WINAPI MsgWaitForMultipleObjectsEx(_In_ DWORD nCount, _In_reads_opt_(nCount) CONST HANDLE *pHandles, _In_ DWORD dwMilliseconds, _In_ DWORD dwWakeMask, _In_ DWORD dwFlags)
#define PM_NOYIELD
Definition: winuser.h:1200
BOOL WINAPI PeekMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT, _In_ UINT)
BOOL WINAPI PostThreadMessageW(_In_ DWORD, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define PM_REMOVE
Definition: winuser.h:1199
#define CreateWindowW(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4319
LRESULT WINAPI DispatchMessageW(_In_ const MSG *)
#define WM_USER
Definition: winuser.h:1898
#define QS_PAINT
Definition: winuser.h:882
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
#define MWMO_WAITALL
Definition: winuser.h:911
BOOL WINAPI DestroyWindow(_In_ HWND)
#define PM_NOREMOVE
Definition: winuser.h:1198
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193