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
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41 #include "wine/unicode.h"
42 #include "wine/obj_base.h"
43 #include "wine/obj_clientserver.h"
44 #include "wine/obj_misc.h"
45 #include "wine/obj_marshal.h"
46 #include "wine/obj_storage.h"
47 #include "wine/obj_channel.h"
48 #include "compobj_private.h"
50 #include "wine/debug.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
54 /****************************************************************************
55 * This section defines variables internal to the COM module.
57 * TODO: Most of these things will have to be made thread-safe.
59 HINSTANCE COMPOBJ_hInstance32
= 0;
61 static HRESULT
COM_GetRegisteredClassObject(REFCLSID rclsid
, DWORD dwClsContext
, LPUNKNOWN
* ppUnk
);
62 static void COM_RevokeAllClasses();
63 static void COM_ExternalLockFreeList();
65 /*****************************************************************************
66 * Appartment management stuff
69 * per Thread values are stored in the TEB on offset 0xF80
71 * see www.microsoft.com/msj/1099/bugslayer/bugslayer1099.htm
76 unsigned char threadingModell
; /* we use the COINIT flags */
77 unsigned long threadID
;
78 long AppartmentLockCount
;
82 OleAppartmentData
*AppartmentData
;
86 static CRITICAL_SECTION csAppartmentData = CRITICAL_SECTION_INIT("csAppartmentData");
89 * the first STA created in a process is the main STA
93 static OleAppartmentData * mainSTA;
97 * a Process can only have one MTA
101 static OleAppartmentData * processMTA;
106 * This lock count counts the number of times CoInitialize is called. It is
107 * decreased every time CoUninitialize is called. When it hits 0, the COM
108 * libraries are freed
110 static LONG s_COMLockCount
= 0;
113 * This linked list contains the list of registered class objects. These
114 * are mostly used to register the factories for out-of-proc servers of OLE
117 * TODO: Make this data structure aware of inter-process communication. This
118 * means that parts of this will be exported to the Wine Server.
120 typedef struct tagRegisteredClass
122 CLSID classIdentifier
;
123 LPUNKNOWN classObject
;
127 HANDLE hThread
; /* only for localserver */
128 struct tagRegisteredClass
* nextClass
;
131 static CRITICAL_SECTION csRegisteredClassList
= CRITICAL_SECTION_INIT("csRegisteredClassList");
132 static RegisteredClass
* firstRegisteredClass
= NULL
;
134 /*****************************************************************************
135 * This section contains OpenDllList definitions
137 * The OpenDllList contains only handles of dll loaded by CoGetClassObject or
138 * other functions what do LoadLibrary _without_ giving back a HMODULE.
139 * Without this list these handles would be freed never.
141 * FIXME: a DLL what says OK whenn asked for unloading is unloaded in the
142 * next unload-call but not before 600 sec.
145 typedef struct tagOpenDll
{
147 struct tagOpenDll
*next
;
150 static CRITICAL_SECTION csOpenDllList
= CRITICAL_SECTION_INIT("csOpenDllList");
151 static OpenDll
*openDllList
= NULL
; /* linked list of open dlls */
153 static void COMPOBJ_DLLList_Add(HANDLE hLibrary
);
154 static void COMPOBJ_DllList_FreeUnused(int Timeout
);
157 /******************************************************************************
158 * Initialize/Uninitialize critical sections.
160 void COMPOBJ_InitProcess( void )
164 void COMPOBJ_UninitProcess( void )
168 /*****************************************************************************
169 * This section contains OpenDllList implemantation
172 static void COMPOBJ_DLLList_Add(HANDLE hLibrary
)
179 EnterCriticalSection( &csOpenDllList
);
181 if (openDllList
== NULL
) {
182 /* empty list -- add first node */
183 openDllList
= (OpenDll
*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll
));
184 openDllList
->hLibrary
=hLibrary
;
185 openDllList
->next
= NULL
;
187 /* search for this dll */
189 for (ptr
= openDllList
; ptr
->next
!= NULL
; ptr
=ptr
->next
) {
190 if (ptr
->hLibrary
== hLibrary
) {
196 /* dll not found, add it */
198 openDllList
= (OpenDll
*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll
));
199 openDllList
->hLibrary
= hLibrary
;
200 openDllList
->next
= tmp
;
204 LeaveCriticalSection( &csOpenDllList
);
207 static void COMPOBJ_DllList_FreeUnused(int Timeout
)
209 OpenDll
*curr
, *next
, *prev
= NULL
;
210 typedef HRESULT(*DllCanUnloadNowFunc
)(void);
211 DllCanUnloadNowFunc DllCanUnloadNow
;
215 EnterCriticalSection( &csOpenDllList
);
217 for (curr
= openDllList
; curr
!= NULL
; ) {
218 DllCanUnloadNow
= (DllCanUnloadNowFunc
) GetProcAddress(curr
->hLibrary
, "DllCanUnloadNow");
220 if ( (DllCanUnloadNow
!= NULL
) && (DllCanUnloadNow() == S_OK
) ) {
223 TRACE("freeing 0x%08x\n", curr
->hLibrary
);
224 FreeLibrary(curr
->hLibrary
);
226 HeapFree(GetProcessHeap(), 0, curr
);
227 if (curr
== openDllList
) {
240 LeaveCriticalSection( &csOpenDllList
);
243 /******************************************************************************
244 * CoBuildVersion [COMPOBJ.1]
245 * CoBuildVersion [OLE32.4]
248 * Current build version, hiword is majornumber, loword is minornumber
250 DWORD WINAPI
CoBuildVersion(void)
252 TRACE("Returning version %d, build %d.\n", rmm
, rup
);
253 return (rmm
<<16)+rup
;
256 /******************************************************************************
257 * CoInitialize [OLE32.26]
259 * Initializes the COM libraries.
263 HRESULT WINAPI
CoInitialize(
264 LPVOID lpReserved
/* [in] pointer to win32 malloc interface
265 (obsolete, should be NULL) */
269 * Just delegate to the newer method.
271 return CoInitializeEx(lpReserved
, COINIT_APARTMENTTHREADED
);
274 /******************************************************************************
275 * CoInitializeEx [OLE32.163]
277 * Initializes the COM libraries. The behavior used to set the win32 IMalloc
278 * used for memory management is obsolete.
281 * S_OK if successful,
282 * S_FALSE if this function was called already.
283 * RPC_E_CHANGED_MODE if a previous call to CoInitialize specified another
287 * Only the single threaded model is supported. As a result RPC_E_CHANGED_MODE
290 * See the windows documentation for more details.
292 HRESULT WINAPI
CoInitializeEx(
293 LPVOID lpReserved
, /* [in] pointer to win32 malloc interface
294 (obsolete, should be NULL) */
295 DWORD dwCoInit
/* [in] A value from COINIT specifies the threading model */
300 TRACE("(%p, %x)\n", lpReserved
, (int)dwCoInit
);
302 if (lpReserved
!=NULL
)
304 ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved
, (int)dwCoInit
, lpReserved
);
308 * Check for unsupported features.
310 if (dwCoInit
!=COINIT_APARTMENTTHREADED
)
312 FIXME(":(%p,%x): unsupported flag %x\n", lpReserved
, (int)dwCoInit
, (int)dwCoInit
);
313 /* Hope for the best and continue anyway */
317 * Check the lock count. If this is the first time going through the initialize
318 * process, we have to initialize the libraries.
320 * And crank-up that lock count.
322 if (InterlockedExchangeAdd(&s_COMLockCount
,1)==0)
325 * Initialize the various COM libraries and data structures.
327 TRACE("() - Initializing the COM libraries\n");
330 RunningObjectTableImpl_Initialize();
340 /***********************************************************************
341 * CoUninitialize [OLE32.47]
343 * This method will release the COM libraries.
345 * See the windows documentation for more details.
347 void WINAPI
CoUninitialize(void)
353 * Decrease the reference count.
354 * If we are back to 0 locks on the COM library, make sure we free
355 * all the associated data structures.
357 lCOMRefCnt
= InterlockedExchangeAdd(&s_COMLockCount
,-1);
361 * Release the various COM libraries and data structures.
363 TRACE("() - Releasing the COM libraries\n");
365 RunningObjectTableImpl_UnInitialize();
367 * Release the references to the registered class objects.
369 COM_RevokeAllClasses();
372 * This will free the loaded COM Dlls.
374 CoFreeAllLibraries();
377 * This will free list of external references to COM objects.
379 COM_ExternalLockFreeList();
382 else if (lCOMRefCnt
<1) {
383 ERR( "CoUninitialize() - not CoInitialized.\n" );
384 InterlockedExchangeAdd(&s_COMLockCount
,1); /* restore the lock count. */
388 /******************************************************************************
389 * CoDisconnectObject [COMPOBJ.15]
390 * CoDisconnectObject [OLE32.8]
392 HRESULT WINAPI
CoDisconnectObject( LPUNKNOWN lpUnk
, DWORD reserved
)
394 TRACE("(%p, %lx)\n",lpUnk
,reserved
);
398 /******************************************************************************
399 * CoCreateGuid[OLE32.6]
402 HRESULT WINAPI
CoCreateGuid(
403 GUID
*pguid
/* [out] points to the GUID to initialize */
405 return UuidCreate(pguid
);
408 /******************************************************************************
409 * CLSIDFromString [OLE32.3]
410 * IIDFromString [OLE32.74]
411 * Converts a unique identifier from its string representation into
415 * If idstr is not a valid CLSID string then it gets treated as a ProgID
420 HRESULT WINAPI
__CLSIDFromStringA(
421 LPCSTR idstr
, /* [in] string representation of guid */
422 CLSID
*id
) /* [out] GUID converted from string */
424 BYTE
*s
= (BYTE
*) idstr
;
429 s
= "{00000000-0000-0000-0000-000000000000}";
430 else { /* validate the CLSID string */
433 return CO_E_CLASSSTRING
;
435 if ((s
[0]!='{') || (s
[9]!='-') || (s
[14]!='-') || (s
[19]!='-') || (s
[24]!='-') || (s
[37]!='}'))
436 return CO_E_CLASSSTRING
;
438 for (i
=1; i
<37; i
++) {
439 if ((i
== 9)||(i
== 14)||(i
== 19)||(i
== 24)) continue;
440 if (!(((s
[i
] >= '0') && (s
[i
] <= '9')) ||
441 ((s
[i
] >= 'a') && (s
[i
] <= 'f')) ||
442 ((s
[i
] >= 'A') && (s
[i
] <= 'F'))))
443 return CO_E_CLASSSTRING
;
447 TRACE("%s -> %p\n", s
, id
);
449 /* quick lookup table */
450 memset(table
, 0, 256);
452 for (i
= 0; i
< 10; i
++) {
455 for (i
= 0; i
< 6; i
++) {
456 table
['A' + i
] = i
+10;
457 table
['a' + i
] = i
+10;
460 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
462 id
->Data1
= (table
[s
[1]] << 28 | table
[s
[2]] << 24 | table
[s
[3]] << 20 | table
[s
[4]] << 16 |
463 table
[s
[5]] << 12 | table
[s
[6]] << 8 | table
[s
[7]] << 4 | table
[s
[8]]);
464 id
->Data2
= table
[s
[10]] << 12 | table
[s
[11]] << 8 | table
[s
[12]] << 4 | table
[s
[13]];
465 id
->Data3
= table
[s
[15]] << 12 | table
[s
[16]] << 8 | table
[s
[17]] << 4 | table
[s
[18]];
467 /* these are just sequential bytes */
468 id
->Data4
[0] = table
[s
[20]] << 4 | table
[s
[21]];
469 id
->Data4
[1] = table
[s
[22]] << 4 | table
[s
[23]];
470 id
->Data4
[2] = table
[s
[25]] << 4 | table
[s
[26]];
471 id
->Data4
[3] = table
[s
[27]] << 4 | table
[s
[28]];
472 id
->Data4
[4] = table
[s
[29]] << 4 | table
[s
[30]];
473 id
->Data4
[5] = table
[s
[31]] << 4 | table
[s
[32]];
474 id
->Data4
[6] = table
[s
[33]] << 4 | table
[s
[34]];
475 id
->Data4
[7] = table
[s
[35]] << 4 | table
[s
[36]];
480 /*****************************************************************************/
482 HRESULT WINAPI
CLSIDFromString(
483 LPCOLESTR idstr
, /* [in] string representation of GUID */
484 CLSID
*id
) /* [out] GUID represented by above string */
489 if (!WideCharToMultiByte( CP_ACP
, 0, idstr
, -1, xid
, sizeof(xid
), NULL
, NULL
))
490 return CO_E_CLASSSTRING
;
493 ret
= __CLSIDFromStringA(xid
,id
);
494 if(ret
!= S_OK
) { /* It appears a ProgID is also valid */
495 ret
= CLSIDFromProgID(idstr
, id
);
500 /******************************************************************************
501 * WINE_StringFromCLSID [Internal]
502 * Converts a GUID into the respective string representation.
507 * the string representation and HRESULT
509 HRESULT
WINE_StringFromCLSID(
510 const CLSID
*id
, /* [in] GUID to be converted */
511 LPSTR idstr
/* [out] pointer to buffer to contain converted guid */
513 static const char *hex
= "0123456789ABCDEF";
518 { ERR("called with id=Null\n");
523 sprintf(idstr
, "{%08lX-%04X-%04X-%02X%02X-",
524 id
->Data1
, id
->Data2
, id
->Data3
,
525 id
->Data4
[0], id
->Data4
[1]);
529 for (i
= 2; i
< 8; i
++) {
530 *s
++ = hex
[id
->Data4
[i
]>>4];
531 *s
++ = hex
[id
->Data4
[i
] & 0xf];
537 TRACE("%p->%s\n", id
, idstr
);
543 /******************************************************************************
544 * StringFromCLSID [OLE32.151]
545 * StringFromIID [OLE32.153]
546 * Converts a GUID into the respective string representation.
547 * The target string is allocated using the OLE IMalloc.
549 * the string representation and HRESULT
551 HRESULT WINAPI
StringFromCLSID(
552 REFCLSID id
, /* [in] the GUID to be converted */
553 LPOLESTR
*idstr
/* [out] a pointer to a to-be-allocated pointer pointing to the resulting string */
559 if ((ret
=CoGetMalloc(0,&mllc
)))
562 ret
=WINE_StringFromCLSID(id
,buf
);
564 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, buf
, -1, NULL
, 0 );
565 *idstr
= IMalloc_Alloc( mllc
, len
* sizeof(WCHAR
) );
566 MultiByteToWideChar( CP_ACP
, 0, buf
, -1, *idstr
, len
);
571 /******************************************************************************
572 * StringFromGUID2 [COMPOBJ.76]
573 * StringFromGUID2 [OLE32.152]
575 * Converts a global unique identifier into a string of an API-
576 * specified fixed format. (The usual {.....} stuff.)
579 * The (UNICODE) string representation of the GUID in 'str'
580 * The length of the resulting string, 0 if there was any problem.
583 StringFromGUID2(REFGUID id
, LPOLESTR str
, INT cmax
)
587 if (WINE_StringFromCLSID(id
,xguid
))
589 return MultiByteToWideChar( CP_ACP
, 0, xguid
, -1, str
, cmax
);
592 /******************************************************************************
593 * ProgIDFromCLSID [OLE32.133]
594 * Converts a class id into the respective Program ID. (By using a registry lookup)
595 * RETURNS S_OK on success
596 * riid associated with the progid
599 HRESULT WINAPI
ProgIDFromCLSID(
600 REFCLSID clsid
, /* [in] class id as found in registry */
601 LPOLESTR
*lplpszProgID
/* [out] associated Prog ID */
604 char strCLSID
[50], *buf
, *buf2
;
610 WINE_StringFromCLSID(clsid
, strCLSID
);
612 buf
= HeapAlloc(GetProcessHeap(), 0, strlen(strCLSID
)+14);
613 sprintf(buf
,"CLSID\\%s\\ProgID", strCLSID
);
614 if (RegOpenKeyA(HKEY_CLASSES_ROOT
, buf
, &xhkey
))
615 ret
= REGDB_E_CLASSNOTREG
;
617 HeapFree(GetProcessHeap(), 0, buf
);
621 buf2
= HeapAlloc(GetProcessHeap(), 0, 255);
623 if (RegQueryValueA(xhkey
, NULL
, buf2
, &buf2len
))
624 ret
= REGDB_E_CLASSNOTREG
;
628 if (CoGetMalloc(0,&mllc
))
632 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, buf2
, -1, NULL
, 0 );
633 *lplpszProgID
= IMalloc_Alloc(mllc
, len
* sizeof(WCHAR
) );
634 MultiByteToWideChar( CP_ACP
, 0, buf2
, -1, *lplpszProgID
, len
);
637 HeapFree(GetProcessHeap(), 0, buf2
);
644 /******************************************************************************
645 * CLSIDFromProgID [OLE32.2]
646 * Converts a program id into the respective GUID. (By using a registry lookup)
648 * riid associated with the progid
650 HRESULT WINAPI
CLSIDFromProgID(
651 LPCOLESTR progid
, /* [in] program id as found in registry */
652 LPCLSID riid
) /* [out] associated CLSID */
654 static const WCHAR clsidW
[] = { '\\','C','L','S','I','D',0 };
656 DWORD buf2len
= sizeof(buf2
);
659 WCHAR
*buf
= HeapAlloc( GetProcessHeap(),0,(strlenW(progid
)+8) * sizeof(WCHAR
) );
660 strcpyW( buf
, progid
);
661 strcatW( buf
, clsidW
);
662 if (RegOpenKeyW(HKEY_CLASSES_ROOT
,buf
,&xhkey
))
664 HeapFree(GetProcessHeap(),0,buf
);
665 return CO_E_CLASSSTRING
;
667 HeapFree(GetProcessHeap(),0,buf
);
669 if (RegQueryValueA(xhkey
,NULL
,buf2
,&buf2len
))
672 return CO_E_CLASSSTRING
;
675 return __CLSIDFromStringA(buf2
,riid
);
680 /*****************************************************************************
681 * CoGetPSClsid [OLE32.22]
683 * This function returns the CLSID of the DLL that implements the proxy and stub
684 * for the specified interface.
686 * It determines this by searching the
687 * HKEY_CLASSES_ROOT\Interface\{string form of riid}\ProxyStubClsid32 in the registry
688 * and any interface id registered by CoRegisterPSClsid within the current process.
690 * FIXME: We only search the registry, not ids registered with CoRegisterPSClsid.
692 HRESULT WINAPI
CoGetPSClsid(
693 REFIID riid
, /* [in] Interface whose proxy/stub CLSID is to be returned */
694 CLSID
*pclsid
) /* [out] Where to store returned proxy/stub CLSID */
700 TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid
), pclsid
);
702 /* Get the input iid as a string */
703 WINE_StringFromCLSID(riid
, buf2
);
704 /* Allocate memory for the registry key we will construct.
705 (length of iid string plus constant length of static text */
706 buf
= HeapAlloc(GetProcessHeap(), 0, strlen(buf2
)+27);
709 return (E_OUTOFMEMORY
);
712 /* Construct the registry key we want */
713 sprintf(buf
,"Interface\\%s\\ProxyStubClsid32", buf2
);
716 if (RegOpenKeyA(HKEY_CLASSES_ROOT
, buf
, &xhkey
))
718 HeapFree(GetProcessHeap(),0,buf
);
719 return (E_INVALIDARG
);
721 HeapFree(GetProcessHeap(),0,buf
);
723 /* ... Once we have the key, query the registry to get the
724 value of CLSID as a string, and convert it into a
725 proper CLSID structure to be passed back to the app */
726 buf2len
= sizeof(buf2
);
727 if ( (RegQueryValueA(xhkey
,NULL
,buf2
,&buf2len
)) )
734 /* We have the CLSid we want back from the registry as a string, so
735 lets convert it into a CLSID structure */
736 if ( (__CLSIDFromStringA(buf2
,pclsid
)) != NOERROR
) {
740 TRACE ("() Returning CLSID=%s\n", debugstr_guid(pclsid
));
746 /***********************************************************************
747 * WriteClassStm (OLE32.159)
749 * This function write a CLSID on stream
751 HRESULT WINAPI
WriteClassStm(IStream
*pStm
,REFCLSID rclsid
)
753 TRACE("(%p,%p)\n",pStm
,rclsid
);
758 return IStream_Write(pStm
,rclsid
,sizeof(CLSID
),NULL
);
761 /***********************************************************************
762 * ReadClassStm (OLE32.135)
764 * This function read a CLSID from a stream
766 HRESULT WINAPI
ReadClassStm(IStream
*pStm
,CLSID
*pclsid
)
771 TRACE("(%p,%p)\n",pStm
,pclsid
);
776 res
= IStream_Read(pStm
,(void*)pclsid
,sizeof(CLSID
),&nbByte
);
781 if (nbByte
!= sizeof(CLSID
))
789 * COM_GetRegisteredClassObject
791 * This internal method is used to scan the registered class list to
792 * find a class object.
795 * rclsid Class ID of the class to find.
796 * dwClsContext Class context to match.
797 * ppv [out] returns a pointer to the class object. Complying
798 * to normal COM usage, this method will increase the
799 * reference count on this object.
801 static HRESULT
COM_GetRegisteredClassObject(
806 HRESULT hr
= S_FALSE
;
807 RegisteredClass
* curClass
;
809 EnterCriticalSection( &csRegisteredClassList
);
817 * Iterate through the whole list and try to match the class ID.
819 curClass
= firstRegisteredClass
;
821 while (curClass
!= 0)
824 * Check if we have a match on the class ID.
826 if (IsEqualGUID(&(curClass
->classIdentifier
), rclsid
))
829 * Since we don't do out-of process or DCOM just right away, let's ignore the
834 * We have a match, return the pointer to the class object.
836 *ppUnk
= curClass
->classObject
;
838 IUnknown_AddRef(curClass
->classObject
);
845 * Step to the next class in the list.
847 curClass
= curClass
->nextClass
;
851 LeaveCriticalSection( &csRegisteredClassList
);
853 * If we get to here, we haven't found our class.
859 _LocalServerThread(LPVOID param
) {
862 RegisteredClass
*newClass
= (RegisteredClass
*)param
;
866 unsigned char *buffer
;
868 IClassFactory
*classfac
;
869 LARGE_INTEGER seekto
;
870 ULARGE_INTEGER newpos
;
873 TRACE("Starting threader for %s.\n",debugstr_guid(&newClass
->classIdentifier
));
874 strcpy(pipefn
,PIPEPREF
);
875 WINE_StringFromCLSID(&newClass
->classIdentifier
,pipefn
+strlen(PIPEPREF
));
877 hres
= IUnknown_QueryInterface(newClass
->classObject
,&IID_IClassFactory
,(LPVOID
*)&classfac
);
878 if (hres
) return hres
;
880 hres
= CreateStreamOnHGlobal(0,TRUE
,&pStm
);
882 FIXME("Failed to create stream on hglobal.\n");
885 hres
= CoMarshalInterface(pStm
,&IID_IClassFactory
,(LPVOID
)classfac
,0,NULL
,0);
887 FIXME("CoMarshalInterface failed, %lx!\n",hres
);
890 hres
= IStream_Stat(pStm
,&ststg
,0);
891 if (hres
) return hres
;
893 buflen
= ststg
.cbSize
.s
.LowPart
;
894 buffer
= HeapAlloc(GetProcessHeap(),0,buflen
);
895 seekto
.s
.LowPart
= 0;
896 seekto
.s
.HighPart
= 0;
897 hres
= IStream_Seek(pStm
,seekto
,SEEK_SET
,&newpos
);
899 FIXME("IStream_Seek failed, %lx\n",hres
);
902 hres
= IStream_Read(pStm
,buffer
,buflen
,&res
);
904 FIXME("Stream Read failed, %lx\n",hres
);
907 IStream_Release(pStm
);
910 hPipe
= CreateNamedPipeA(
913 PIPE_TYPE_BYTE
|PIPE_WAIT
,
914 PIPE_UNLIMITED_INSTANCES
,
917 NMPWAIT_USE_DEFAULT_WAIT
,
920 if (hPipe
== INVALID_HANDLE_VALUE
) {
921 FIXME("pipe creation failed for %s, le is %lx\n",pipefn
,GetLastError());
924 if (!ConnectNamedPipe(hPipe
,NULL
)) {
925 ERR("Failure during ConnectNamedPipe %lx, ABORT!\n",GetLastError());
929 WriteFile(hPipe
,buffer
,buflen
,&res
,NULL
);
935 /******************************************************************************
936 * CoRegisterClassObject [OLE32.36]
938 * This method will register the class object for a given class ID.
940 * See the Windows documentation for more details.
942 HRESULT WINAPI
CoRegisterClassObject(
945 DWORD dwClsContext
, /* [in] CLSCTX flags indicating the context in which to run the executable */
946 DWORD flags
, /* [in] REGCLS flags indicating how connections are made */
950 RegisteredClass
* newClass
;
951 LPUNKNOWN foundObject
;
954 TRACE("(%s,%p,0x%08lx,0x%08lx,%p)\n",
955 debugstr_guid(rclsid
),pUnk
,dwClsContext
,flags
,lpdwRegister
);
957 if ( (lpdwRegister
==0) || (pUnk
==0) )
963 * First, check if the class is already registered.
964 * If it is, this should cause an error.
966 hr
= COM_GetRegisteredClassObject(rclsid
, dwClsContext
, &foundObject
);
968 IUnknown_Release(foundObject
);
969 return CO_E_OBJISREG
;
972 newClass
= HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass
));
973 if ( newClass
== NULL
)
974 return E_OUTOFMEMORY
;
976 EnterCriticalSection( &csRegisteredClassList
);
978 newClass
->classIdentifier
= *rclsid
;
979 newClass
->runContext
= dwClsContext
;
980 newClass
->connectFlags
= flags
;
982 * Use the address of the chain node as the cookie since we are sure it's
985 newClass
->dwCookie
= (DWORD
)newClass
;
986 newClass
->nextClass
= firstRegisteredClass
;
989 * Since we're making a copy of the object pointer, we have to increase its
992 newClass
->classObject
= pUnk
;
993 IUnknown_AddRef(newClass
->classObject
);
995 firstRegisteredClass
= newClass
;
996 LeaveCriticalSection( &csRegisteredClassList
);
998 *lpdwRegister
= newClass
->dwCookie
;
1000 if (dwClsContext
& CLSCTX_LOCAL_SERVER
) {
1004 newClass
->hThread
=CreateThread(NULL
,0,_LocalServerThread
,newClass
,0,&tid
);
1009 /***********************************************************************
1010 * CoRevokeClassObject [OLE32.40]
1012 * This method will remove a class object from the class registry
1014 * See the Windows documentation for more details.
1016 HRESULT WINAPI
CoRevokeClassObject(
1019 HRESULT hr
= E_INVALIDARG
;
1020 RegisteredClass
** prevClassLink
;
1021 RegisteredClass
* curClass
;
1023 TRACE("(%08lx)\n",dwRegister
);
1025 EnterCriticalSection( &csRegisteredClassList
);
1028 * Iterate through the whole list and try to match the cookie.
1030 curClass
= firstRegisteredClass
;
1031 prevClassLink
= &firstRegisteredClass
;
1033 while (curClass
!= 0)
1036 * Check if we have a match on the cookie.
1038 if (curClass
->dwCookie
== dwRegister
)
1041 * Remove the class from the chain.
1043 *prevClassLink
= curClass
->nextClass
;
1046 * Release the reference to the class object.
1048 IUnknown_Release(curClass
->classObject
);
1051 * Free the memory used by the chain node.
1053 HeapFree(GetProcessHeap(), 0, curClass
);
1060 * Step to the next class in the list.
1062 prevClassLink
= &(curClass
->nextClass
);
1063 curClass
= curClass
->nextClass
;
1067 LeaveCriticalSection( &csRegisteredClassList
);
1069 * If we get to here, we haven't found our class.
1074 /***********************************************************************
1075 * compobj_RegReadPath [internal]
1077 * Reads a registry value and expands it when nessesary
1079 HRESULT
compobj_RegReadPath(char * keyname
, char * valuename
, char * dst
, int dstlen
)
1085 DWORD dwLength
= dstlen
;
1087 if((hres
= RegOpenKeyExA(HKEY_CLASSES_ROOT
, keyname
, 0, KEY_READ
, &key
)) == ERROR_SUCCESS
) {
1088 if( (hres
= RegQueryValueExA(key
, NULL
, NULL
, &keytype
, (LPBYTE
)src
, &dwLength
)) == ERROR_SUCCESS
) {
1089 if (keytype
== REG_EXPAND_SZ
) {
1090 if (dstlen
<= ExpandEnvironmentStringsA(src
, dst
, dstlen
)) hres
= ERROR_MORE_DATA
;
1092 strncpy(dst
, src
, dstlen
);
1100 /***********************************************************************
1101 * CoGetClassObject [COMPOBJ.7]
1102 * CoGetClassObject [OLE32.16]
1104 * FIXME. If request allows of several options and there is a failure
1105 * with one (other than not being registered) do we try the
1106 * others or return failure? (E.g. inprocess is registered but
1107 * the DLL is not found but the server version works)
1109 HRESULT WINAPI
CoGetClassObject(
1110 REFCLSID rclsid
, DWORD dwClsContext
, COSERVERINFO
*pServerInfo
,
1111 REFIID iid
, LPVOID
*ppv
1113 LPUNKNOWN regClassObject
;
1114 HRESULT hres
= E_UNEXPECTED
;
1117 typedef HRESULT (CALLBACK
*DllGetClassObjectFunc
)(REFCLSID clsid
, REFIID iid
, LPVOID
*ppv
);
1118 DllGetClassObjectFunc DllGetClassObject
;
1120 WINE_StringFromCLSID((LPCLSID
)rclsid
,xclsid
);
1122 TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n", debugstr_guid(rclsid
), debugstr_guid(iid
));
1125 FIXME("\tpServerInfo: name=%s\n",debugstr_w(pServerInfo
->pwszName
));
1126 FIXME("\t\tpAuthInfo=%p\n",pServerInfo
->pAuthInfo
);
1130 * First, try and see if we can't match the class ID with one of the
1131 * registered classes.
1133 if (S_OK
== COM_GetRegisteredClassObject(rclsid
, dwClsContext
, ®ClassObject
))
1136 * Get the required interface from the retrieved pointer.
1138 hres
= IUnknown_QueryInterface(regClassObject
, iid
, ppv
);
1141 * Since QI got another reference on the pointer, we want to release the
1142 * one we already have. If QI was unsuccessful, this will release the object. This
1143 * is good since we are not returning it in the "out" parameter.
1145 IUnknown_Release(regClassObject
);
1150 /* first try: in-process */
1151 if ((CLSCTX_INPROC_SERVER
| CLSCTX_INPROC_HANDLER
) & dwClsContext
) {
1152 char keyname
[MAX_PATH
];
1153 char dllpath
[MAX_PATH
+1];
1155 sprintf(keyname
,"CLSID\\%s\\InprocServer32",xclsid
);
1157 if ( compobj_RegReadPath(keyname
, NULL
, dllpath
, sizeof(dllpath
)) != ERROR_SUCCESS
) {
1158 /* failure: CLSID is not found in registry */
1159 WARN("class %s not registred\n", xclsid
);
1160 hres
= REGDB_E_CLASSNOTREG
;
1162 if ((hLibrary
= LoadLibraryExA(dllpath
, 0, LOAD_WITH_ALTERED_SEARCH_PATH
)) == 0) {
1163 /* failure: DLL could not be loaded */
1164 ERR("couldn't load InprocServer32 dll %s\n", dllpath
);
1165 hres
= E_ACCESSDENIED
; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
1166 } else if (!(DllGetClassObject
= (DllGetClassObjectFunc
)GetProcAddress(hLibrary
, "DllGetClassObject"))) {
1167 /* failure: the dll did not export DllGetClassObject */
1168 ERR("couldn't find function DllGetClassObject in %s\n", dllpath
);
1169 FreeLibrary( hLibrary
);
1170 hres
= CO_E_DLLNOTFOUND
;
1172 /* OK: get the ClassObject */
1173 COMPOBJ_DLLList_Add( hLibrary
);
1174 return DllGetClassObject(rclsid
, iid
, ppv
);
1179 /* Next try out of process */
1180 if (CLSCTX_LOCAL_SERVER
& dwClsContext
)
1182 return create_marshalled_proxy(rclsid
,iid
,ppv
);
1185 /* Finally try remote */
1186 if (CLSCTX_REMOTE_SERVER
& dwClsContext
)
1188 FIXME ("CLSCTX_REMOTE_SERVER not supported\n");
1189 hres
= E_NOINTERFACE
;
1194 /***********************************************************************
1195 * CoResumeClassObjects (OLE32.173)
1197 * Resumes classobjects registered with REGCLS suspended
1199 HRESULT WINAPI
CoResumeClassObjects(void)
1205 /***********************************************************************
1206 * GetClassFile (OLE32.67)
1208 * This function supplies the CLSID associated with the given filename.
1210 HRESULT WINAPI
GetClassFile(LPCOLESTR filePathName
,CLSID
*pclsid
)
1214 int nbElm
, length
, i
;
1216 LPOLESTR
*pathDec
=0,absFile
=0,progId
=0;
1218 static const WCHAR bkslashW
[] = {'\\',0};
1219 static const WCHAR dotW
[] = {'.',0};
1221 TRACE("%s, %p\n", debugstr_w(filePathName
), pclsid
);
1223 /* if the file contain a storage object the return the CLSID writen by IStorage_SetClass method*/
1224 if((StgIsStorageFile(filePathName
))==S_OK
){
1226 res
=StgOpenStorage(filePathName
,NULL
,STGM_READ
| STGM_SHARE_DENY_WRITE
,NULL
,0,&pstg
);
1229 res
=ReadClassStg(pstg
,pclsid
);
1231 IStorage_Release(pstg
);
1235 /* if the file is not a storage object then attemps to match various bits in the file against a
1236 pattern in the registry. this case is not frequently used ! so I present only the psodocode for
1239 for(i=0;i<nFileTypes;i++)
1241 for(i=0;j<nPatternsForType;j++){
1246 pat=ReadPatternFromRegistry(i,j);
1247 hFile=CreateFileW(filePathName,,,,,,hFile);
1248 SetFilePosition(hFile,pat.offset);
1249 ReadFile(hFile,buf,pat.size,NULL,NULL);
1250 if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
1252 *pclsid=ReadCLSIDFromRegistry(i);
1258 /* if the obove strategies fail then search for the extension key in the registry */
1260 /* get the last element (absolute file) in the path name */
1261 nbElm
=FileMonikerImpl_DecomposePath(filePathName
,&pathDec
);
1262 absFile
=pathDec
[nbElm
-1];
1264 /* failed if the path represente a directory and not an absolute file name*/
1265 if (!lstrcmpW(absFile
, bkslashW
))
1266 return MK_E_INVALIDEXTENSION
;
1268 /* get the extension of the file */
1270 length
=lstrlenW(absFile
);
1271 for(i
= length
-1; (i
>= 0) && *(extension
= &absFile
[i
]) != '.'; i
--)
1274 if (!extension
|| !lstrcmpW(extension
, dotW
))
1275 return MK_E_INVALIDEXTENSION
;
1277 res
=RegQueryValueW(HKEY_CLASSES_ROOT
, extension
, NULL
, &sizeProgId
);
1279 /* get the progId associated to the extension */
1280 progId
= CoTaskMemAlloc(sizeProgId
);
1281 res
= RegQueryValueW(HKEY_CLASSES_ROOT
, extension
, progId
, &sizeProgId
);
1283 if (res
==ERROR_SUCCESS
)
1284 /* return the clsid associated to the progId */
1285 res
= CLSIDFromProgID(progId
,pclsid
);
1287 for(i
=0; pathDec
[i
]!=NULL
;i
++)
1288 CoTaskMemFree(pathDec
[i
]);
1289 CoTaskMemFree(pathDec
);
1291 CoTaskMemFree(progId
);
1293 if (res
==ERROR_SUCCESS
)
1296 return MK_E_INVALIDEXTENSION
;
1298 /***********************************************************************
1299 * CoCreateInstance [COMPOBJ.13]
1300 * CoCreateInstance [OLE32.7]
1302 HRESULT WINAPI
CoCreateInstance(
1304 LPUNKNOWN pUnkOuter
,
1310 LPCLASSFACTORY lpclf
= 0;
1319 * Initialize the "out" parameter
1324 * Get a class factory to construct the object we want.
1326 hres
= CoGetClassObject(rclsid
,
1333 FIXME("no classfactory created for CLSID %s, hres is 0x%08lx\n",
1334 debugstr_guid(rclsid
),hres
);
1339 * Create the object and don't forget to release the factory
1341 hres
= IClassFactory_CreateInstance(lpclf
, pUnkOuter
, iid
, ppv
);
1342 IClassFactory_Release(lpclf
);
1344 FIXME("no instance created for interface %s of class %s, hres is 0x%08lx\n",
1345 debugstr_guid(iid
), debugstr_guid(rclsid
),hres
);
1350 /***********************************************************************
1351 * CoCreateInstanceEx [OLE32.165]
1353 HRESULT WINAPI
CoCreateInstanceEx(
1355 LPUNKNOWN pUnkOuter
,
1357 COSERVERINFO
* pServerInfo
,
1361 IUnknown
* pUnk
= NULL
;
1364 int successCount
= 0;
1369 if ( (cmq
==0) || (pResults
==NULL
))
1370 return E_INVALIDARG
;
1372 if (pServerInfo
!=NULL
)
1373 FIXME("() non-NULL pServerInfo not supported!\n");
1376 * Initialize all the "out" parameters.
1378 for (index
= 0; index
< cmq
; index
++)
1380 pResults
[index
].pItf
= NULL
;
1381 pResults
[index
].hr
= E_NOINTERFACE
;
1385 * Get the object and get its IUnknown pointer.
1387 hr
= CoCreateInstance(rclsid
,
1397 * Then, query for all the interfaces requested.
1399 for (index
= 0; index
< cmq
; index
++)
1401 pResults
[index
].hr
= IUnknown_QueryInterface(pUnk
,
1402 pResults
[index
].pIID
,
1403 (VOID
**)&(pResults
[index
].pItf
));
1405 if (pResults
[index
].hr
== S_OK
)
1410 * Release our temporary unknown pointer.
1412 IUnknown_Release(pUnk
);
1414 if (successCount
== 0)
1415 return E_NOINTERFACE
;
1417 if (successCount
!=cmq
)
1418 return CO_S_NOTALLINTERFACES
;
1423 /***********************************************************************
1424 * CoLoadLibrary (OLE32.30)
1426 HINSTANCE WINAPI
CoLoadLibrary(LPOLESTR lpszLibName
, BOOL bAutoFree
)
1428 TRACE("(%s, %d)\n", debugstr_w(lpszLibName
), bAutoFree
);
1430 return LoadLibraryExW(lpszLibName
, 0, LOAD_WITH_ALTERED_SEARCH_PATH
);
1433 /***********************************************************************
1434 * CoFreeLibrary [OLE32.13]
1436 * NOTES: don't belive the docu
1438 void WINAPI
CoFreeLibrary(HINSTANCE hLibrary
)
1440 FreeLibrary(hLibrary
);
1444 /***********************************************************************
1445 * CoFreeAllLibraries [OLE32.12]
1447 * NOTES: don't belive the docu
1449 void WINAPI
CoFreeAllLibraries(void)
1455 /***********************************************************************
1456 * CoFreeUnusedLibraries [COMPOBJ.17]
1457 * CoFreeUnusedLibraries [OLE32.14]
1459 * FIXME: Calls to CoFreeUnusedLibraries from any thread always route
1460 * through the main apartment's thread to call DllCanUnloadNow
1462 void WINAPI
CoFreeUnusedLibraries(void)
1464 COMPOBJ_DllList_FreeUnused(0);
1467 /***********************************************************************
1468 * CoFileTimeNow [COMPOBJ.82]
1469 * CoFileTimeNow [OLE32.10]
1472 * the current system time in lpFileTime
1474 HRESULT WINAPI
CoFileTimeNow( FILETIME
*lpFileTime
) /* [out] the current time */
1476 GetSystemTimeAsFileTime( lpFileTime
);
1480 /***********************************************************************
1481 * CoLoadLibrary (OLE32.30)
1483 static void COM_RevokeAllClasses()
1485 EnterCriticalSection( &csRegisteredClassList
);
1487 while (firstRegisteredClass
!=0)
1489 CoRevokeClassObject(firstRegisteredClass
->dwCookie
);
1492 LeaveCriticalSection( &csRegisteredClassList
);
1495 /****************************************************************************
1496 * COM External Lock methods implementation
1498 * This api provides a linked list to managed external references to
1501 * The public interface consists of three calls:
1502 * COM_ExternalLockAddRef
1503 * COM_ExternalLockRelease
1504 * COM_ExternalLockFreeList
1507 #define EL_END_OF_LIST 0
1508 #define EL_NOT_FOUND 0
1511 * Declaration of the static structure that manage the
1512 * external lock to COM objects.
1514 typedef struct COM_ExternalLock COM_ExternalLock
;
1515 typedef struct COM_ExternalLockList COM_ExternalLockList
;
1517 struct COM_ExternalLock
1519 IUnknown
*pUnk
; /* IUnknown referenced */
1520 ULONG uRefCount
; /* external lock counter to IUnknown object*/
1521 COM_ExternalLock
*next
; /* Pointer to next element in list */
1524 struct COM_ExternalLockList
1526 COM_ExternalLock
*head
; /* head of list */
1530 * Declaration and initialization of the static structure that manages
1531 * the external lock to COM objects.
1533 static COM_ExternalLockList elList
= { EL_END_OF_LIST
};
1536 * Private methods used to managed the linked list
1540 static COM_ExternalLock
* COM_ExternalLockLocate(
1541 COM_ExternalLock
*element
,
1544 /****************************************************************************
1545 * Internal - Insert a new IUnknown* to the linked list
1547 static BOOL
COM_ExternalLockInsert(
1550 COM_ExternalLock
*newLock
= NULL
;
1551 COM_ExternalLock
*previousHead
= NULL
;
1554 * Allocate space for the new storage object
1556 newLock
= HeapAlloc(GetProcessHeap(), 0, sizeof(COM_ExternalLock
));
1558 if (newLock
!=NULL
) {
1559 if ( elList
.head
== EL_END_OF_LIST
) {
1560 elList
.head
= newLock
; /* The list is empty */
1562 /* insert does it at the head */
1563 previousHead
= elList
.head
;
1564 elList
.head
= newLock
;
1567 /* Set new list item data member */
1568 newLock
->pUnk
= pUnk
;
1569 newLock
->uRefCount
= 1;
1570 newLock
->next
= previousHead
;
1577 /****************************************************************************
1578 * Internal - Method that removes an item from the linked list.
1580 static void COM_ExternalLockDelete(
1581 COM_ExternalLock
*itemList
)
1583 COM_ExternalLock
*current
= elList
.head
;
1585 if ( current
== itemList
) {
1586 /* this section handles the deletion of the first node */
1587 elList
.head
= itemList
->next
;
1588 HeapFree( GetProcessHeap(), 0, itemList
);
1591 if ( current
->next
== itemList
){ /* We found the item to free */
1592 current
->next
= itemList
->next
; /* readjust the list pointers */
1593 HeapFree( GetProcessHeap(), 0, itemList
);
1597 /* Skip to the next item */
1598 current
= current
->next
;
1600 } while ( current
!= EL_END_OF_LIST
);
1604 /****************************************************************************
1605 * Internal - Recursivity agent for IUnknownExternalLockList_Find
1607 * NOTES: how long can the list be ?? (recursive!!!)
1609 static COM_ExternalLock
* COM_ExternalLockLocate( COM_ExternalLock
*element
, IUnknown
*pUnk
)
1611 if ( element
== EL_END_OF_LIST
)
1612 return EL_NOT_FOUND
;
1613 else if ( element
->pUnk
== pUnk
) /* We found it */
1615 else /* Not the right guy, keep on looking */
1616 return COM_ExternalLockLocate( element
->next
, pUnk
);
1619 /****************************************************************************
1620 * Public - Method that increments the count for a IUnknown* in the linked
1621 * list. The item is inserted if not already in the list.
1623 static void COM_ExternalLockAddRef(IUnknown
*pUnk
)
1625 COM_ExternalLock
*externalLock
= COM_ExternalLockLocate(elList
.head
, pUnk
);
1628 * Add an external lock to the object. If it was already externally
1629 * locked, just increase the reference count. If it was not.
1630 * add the item to the list.
1632 if ( externalLock
== EL_NOT_FOUND
)
1633 COM_ExternalLockInsert(pUnk
);
1635 externalLock
->uRefCount
++;
1638 * Add an internal lock to the object
1640 IUnknown_AddRef(pUnk
);
1643 /****************************************************************************
1644 * Public - Method that decrements the count for a IUnknown* in the linked
1645 * list. The item is removed from the list if its count end up at zero or if
1648 static void COM_ExternalLockRelease(
1652 COM_ExternalLock
*externalLock
= COM_ExternalLockLocate(elList
.head
, pUnk
);
1654 if ( externalLock
!= EL_NOT_FOUND
) {
1656 externalLock
->uRefCount
--; /* release external locks */
1657 IUnknown_Release(pUnk
); /* release local locks as well */
1659 if ( bRelAll
== FALSE
) break; /* perform single release */
1661 } while ( externalLock
->uRefCount
> 0 );
1663 if ( externalLock
->uRefCount
== 0 ) /* get rid of the list entry */
1664 COM_ExternalLockDelete(externalLock
);
1667 /****************************************************************************
1668 * Public - Method that frees the content of the list.
1670 static void COM_ExternalLockFreeList()
1672 COM_ExternalLock
*head
;
1674 head
= elList
.head
; /* grab it by the head */
1675 while ( head
!= EL_END_OF_LIST
) {
1676 COM_ExternalLockDelete(head
); /* get rid of the head stuff */
1677 head
= elList
.head
; /* get the new head... */
1681 /****************************************************************************
1682 * Public - Method that dump the content of the list.
1684 void COM_ExternalLockDump()
1686 COM_ExternalLock
*current
= elList
.head
;
1688 DPRINTF("\nExternal lock list contains:\n");
1690 while ( current
!= EL_END_OF_LIST
) {
1691 DPRINTF( "\t%p with %lu references count.\n", current
->pUnk
, current
->uRefCount
);
1693 /* Skip to the next item */
1694 current
= current
->next
;
1698 /******************************************************************************
1699 * CoLockObjectExternal [OLE32.31]
1701 HRESULT WINAPI
CoLockObjectExternal(
1702 LPUNKNOWN pUnk
, /* [in] object to be locked */
1703 BOOL fLock
, /* [in] do lock */
1704 BOOL fLastUnlockReleases
) /* [in] unlock all */
1709 * Increment the external lock coutner, COM_ExternalLockAddRef also
1710 * increment the object's internal lock counter.
1712 COM_ExternalLockAddRef( pUnk
);
1715 * Decrement the external lock coutner, COM_ExternalLockRelease also
1716 * decrement the object's internal lock counter.
1718 COM_ExternalLockRelease( pUnk
, fLastUnlockReleases
);
1724 /***********************************************************************
1725 * CoInitializeWOW (OLE32.27)
1727 HRESULT WINAPI
CoInitializeWOW(DWORD x
,DWORD y
) {
1728 FIXME("(0x%08lx,0x%08lx),stub!\n",x
,y
);
1732 static IUnknown
* pUnkState
= 0; /* FIXME: thread local */
1733 static int nStatCounter
= 0; /* global */
1734 static HMODULE hOleAut32
= 0; /* global */
1736 /***********************************************************************
1737 * CoGetState [OLE32.24]
1739 * NOTES: might be incomplete
1741 HRESULT WINAPI
CoGetState(IUnknown
** ppv
)
1746 IUnknown_AddRef(pUnkState
);
1748 FIXME("-- %p\n", *ppv
);
1756 /***********************************************************************
1757 * CoSetState [OLE32.42]
1759 * NOTES: FIXME: protect this with a crst
1761 HRESULT WINAPI
CoSetState(IUnknown
* pv
)
1763 FIXME("(%p),stub!\n", pv
);
1766 IUnknown_AddRef(pv
);
1768 if (nStatCounter
== 1) LoadLibraryA("OLEAUT32.DLL");
1772 TRACE("-- release %p now\n", pUnkState
);
1773 IUnknown_Release(pUnkState
);
1775 if (!nStatCounter
) FreeLibrary(hOleAut32
);
1782 /******************************************************************************
1783 * OleGetAutoConvert [OLE32.104]
1785 HRESULT WINAPI
OleGetAutoConvert(REFCLSID clsidOld
, LPCLSID pClsidNew
)
1793 sprintf(buf
,"CLSID\\");WINE_StringFromCLSID(clsidOld
,&buf
[6]);
1794 if (RegOpenKeyA(HKEY_CLASSES_ROOT
,buf
,&hkey
))
1796 res
= REGDB_E_CLASSNOTREG
;
1800 /* we can just query for the default value of AutoConvertTo key like that,
1801 without opening the AutoConvertTo key and querying for NULL (default) */
1802 if (RegQueryValueA(hkey
,"AutoConvertTo",buf
,&len
))
1804 res
= REGDB_E_KEYMISSING
;
1807 MultiByteToWideChar( CP_ACP
, 0, buf
, -1, wbuf
, sizeof(wbuf
)/sizeof(WCHAR
) );
1808 CLSIDFromString(wbuf
,pClsidNew
);
1810 if (hkey
) RegCloseKey(hkey
);
1814 /******************************************************************************
1815 * OleSetAutoConvert [OLE32.126]
1817 HRESULT WINAPI
OleSetAutoConvert(REFCLSID clsidOld
, REFCLSID clsidNew
)
1820 char buf
[200], szClsidNew
[200];
1823 TRACE("(%s,%s)\n", debugstr_guid(clsidOld
), debugstr_guid(clsidNew
));
1824 sprintf(buf
,"CLSID\\");WINE_StringFromCLSID(clsidOld
,&buf
[6]);
1825 WINE_StringFromCLSID(clsidNew
, szClsidNew
);
1826 if (RegOpenKeyA(HKEY_CLASSES_ROOT
,buf
,&hkey
))
1828 res
= REGDB_E_CLASSNOTREG
;
1831 if (RegSetValueA(hkey
, "AutoConvertTo", REG_SZ
, szClsidNew
, strlen(szClsidNew
)+1))
1833 res
= REGDB_E_WRITEREGDB
;
1838 if (hkey
) RegCloseKey(hkey
);
1842 /******************************************************************************
1843 * CoTreatAsClass [OLE32.46]
1845 HRESULT WINAPI
CoTreatAsClass(REFCLSID clsidOld
, REFCLSID clsidNew
)
1848 char buf
[200], szClsidNew
[200];
1851 FIXME("(%s,%s)\n", debugstr_guid(clsidOld
), debugstr_guid(clsidNew
));
1852 sprintf(buf
,"CLSID\\");WINE_StringFromCLSID(clsidOld
,&buf
[6]);
1853 WINE_StringFromCLSID(clsidNew
, szClsidNew
);
1854 if (RegOpenKeyA(HKEY_CLASSES_ROOT
,buf
,&hkey
))
1856 res
= REGDB_E_CLASSNOTREG
;
1859 if (RegSetValueA(hkey
, "AutoTreatAs", REG_SZ
, szClsidNew
, strlen(szClsidNew
)+1))
1861 res
= REGDB_E_WRITEREGDB
;
1866 if (hkey
) RegCloseKey(hkey
);
1871 /***********************************************************************
1872 * IsEqualGUID [OLE32.76]
1874 * Compares two Unique Identifiers.
1880 BOOL WINAPI
IsEqualGUID(
1881 REFGUID rguid1
, /* [in] unique id 1 */
1882 REFGUID rguid2
/* [in] unique id 2 */
1885 return !memcmp(rguid1
,rguid2
,sizeof(GUID
));
1888 /***********************************************************************
1889 * CoInitializeSecurity [OLE32.164]
1891 HRESULT WINAPI
CoInitializeSecurity(PSECURITY_DESCRIPTOR pSecDesc
, LONG cAuthSvc
,
1892 SOLE_AUTHENTICATION_SERVICE
* asAuthSvc
,
1893 void* pReserved1
, DWORD dwAuthnLevel
,
1894 DWORD dwImpLevel
, void* pReserved2
,
1895 DWORD dwCapabilities
, void* pReserved3
)
1897 FIXME("(%p,%ld,%p,%p,%ld,%ld,%p,%ld,%p) - stub!\n", pSecDesc
, cAuthSvc
,
1898 asAuthSvc
, pReserved1
, dwAuthnLevel
, dwImpLevel
, pReserved2
,
1899 dwCapabilities
, pReserved3
);