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
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
42 #include "wine/unicode.h"
44 #include "compobj_private.h"
46 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
50 /****************************************************************************
51 * This section defines variables internal to the COM module.
53 * TODO: Most of these things will have to be made thread-safe.
55 HINSTANCE COMPOBJ_hInstance32
= 0;
57 static HRESULT
COM_GetRegisteredClassObject(REFCLSID rclsid
, DWORD dwClsContext
, LPUNKNOWN
* ppUnk
);
58 static void COM_RevokeAllClasses();
59 static void COM_ExternalLockFreeList();
61 /*****************************************************************************
62 * Appartment management stuff
65 * per Thread values are stored in the TEB on offset 0xF80
67 * see www.microsoft.com/msj/1099/bugslayer/bugslayer1099.htm
72 unsigned char threadingModell
; /* we use the COINIT flags */
73 unsigned long threadID
;
74 long AppartmentLockCount
;
78 OleAppartmentData
*AppartmentData
;
82 static CRITICAL_SECTION csAppartmentData = CRITICAL_SECTION_INIT("csAppartmentData");
85 * the first STA created in a process is the main STA
89 static OleAppartmentData * mainSTA;
93 * a Process can only have one MTA
97 static OleAppartmentData * processMTA;
102 * This lock count counts the number of times CoInitialize is called. It is
103 * decreased every time CoUninitialize is called. When it hits 0, the COM
104 * libraries are freed
106 static LONG s_COMLockCount
= 0;
109 * This linked list contains the list of registered class objects. These
110 * are mostly used to register the factories for out-of-proc servers of OLE
113 * TODO: Make this data structure aware of inter-process communication. This
114 * means that parts of this will be exported to the Wine Server.
116 typedef struct tagRegisteredClass
118 CLSID classIdentifier
;
119 LPUNKNOWN classObject
;
123 HANDLE hThread
; /* only for localserver */
124 struct tagRegisteredClass
* nextClass
;
127 static CRITICAL_SECTION csRegisteredClassList
= CRITICAL_SECTION_INIT("csRegisteredClassList");
128 static RegisteredClass
* firstRegisteredClass
= NULL
;
130 /*****************************************************************************
131 * This section contains OpenDllList definitions
133 * The OpenDllList contains only handles of dll loaded by CoGetClassObject or
134 * other functions what do LoadLibrary _without_ giving back a HMODULE.
135 * Without this list these handles would be freed never.
137 * FIXME: a DLL what says OK whenn asked for unloading is unloaded in the
138 * next unload-call but not before 600 sec.
141 typedef struct tagOpenDll
{
143 struct tagOpenDll
*next
;
146 static CRITICAL_SECTION csOpenDllList
= CRITICAL_SECTION_INIT("csOpenDllList");
147 static OpenDll
*openDllList
= NULL
; /* linked list of open dlls */
149 static void COMPOBJ_DLLList_Add(HANDLE hLibrary
);
150 static void COMPOBJ_DllList_FreeUnused(int Timeout
);
153 /******************************************************************************
154 * Initialize/Uninitialize critical sections.
156 void COMPOBJ_InitProcess( void )
160 void COMPOBJ_UninitProcess( void )
164 /*****************************************************************************
165 * This section contains OpenDllList implemantation
168 static void COMPOBJ_DLLList_Add(HANDLE hLibrary
)
175 EnterCriticalSection( &csOpenDllList
);
177 if (openDllList
== NULL
) {
178 /* empty list -- add first node */
179 openDllList
= (OpenDll
*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll
));
180 openDllList
->hLibrary
=hLibrary
;
181 openDllList
->next
= NULL
;
183 /* search for this dll */
185 for (ptr
= openDllList
; ptr
->next
!= NULL
; ptr
=ptr
->next
) {
186 if (ptr
->hLibrary
== hLibrary
) {
192 /* dll not found, add it */
194 openDllList
= (OpenDll
*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll
));
195 openDllList
->hLibrary
= hLibrary
;
196 openDllList
->next
= tmp
;
200 LeaveCriticalSection( &csOpenDllList
);
203 static void COMPOBJ_DllList_FreeUnused(int Timeout
)
205 OpenDll
*curr
, *next
, *prev
= NULL
;
206 typedef HRESULT(*DllCanUnloadNowFunc
)(void);
207 DllCanUnloadNowFunc DllCanUnloadNow
;
211 EnterCriticalSection( &csOpenDllList
);
213 for (curr
= openDllList
; curr
!= NULL
; ) {
214 DllCanUnloadNow
= (DllCanUnloadNowFunc
) GetProcAddress(curr
->hLibrary
, "DllCanUnloadNow");
216 if ( (DllCanUnloadNow
!= NULL
) && (DllCanUnloadNow() == S_OK
) ) {
219 TRACE("freeing %p\n", curr
->hLibrary
);
220 FreeLibrary(curr
->hLibrary
);
222 HeapFree(GetProcessHeap(), 0, curr
);
223 if (curr
== openDllList
) {
236 LeaveCriticalSection( &csOpenDllList
);
239 /******************************************************************************
240 * CoBuildVersion [COMPOBJ.1]
241 * CoBuildVersion [OLE32.4]
244 * Current build version, hiword is majornumber, loword is minornumber
246 DWORD WINAPI
CoBuildVersion(void)
248 TRACE("Returning version %d, build %d.\n", rmm
, rup
);
249 return (rmm
<<16)+rup
;
252 /******************************************************************************
253 * CoInitialize [OLE32.26]
255 * Initializes the COM libraries.
259 HRESULT WINAPI
CoInitialize(
260 LPVOID lpReserved
/* [in] pointer to win32 malloc interface
261 (obsolete, should be NULL) */
265 * Just delegate to the newer method.
267 return CoInitializeEx(lpReserved
, COINIT_APARTMENTTHREADED
);
270 /******************************************************************************
271 * CoInitializeEx [OLE32.163]
273 * Initializes the COM libraries. The behavior used to set the win32 IMalloc
274 * used for memory management is obsolete.
277 * S_OK if successful,
278 * S_FALSE if this function was called already.
279 * RPC_E_CHANGED_MODE if a previous call to CoInitialize specified another
283 * Only the single threaded model is supported. As a result RPC_E_CHANGED_MODE
286 * See the windows documentation for more details.
288 HRESULT WINAPI
CoInitializeEx(
289 LPVOID lpReserved
, /* [in] pointer to win32 malloc interface
290 (obsolete, should be NULL) */
291 DWORD dwCoInit
/* [in] A value from COINIT specifies the threading model */
296 TRACE("(%p, %x)\n", lpReserved
, (int)dwCoInit
);
298 if (lpReserved
!=NULL
)
300 ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved
, (int)dwCoInit
, lpReserved
);
304 * Check for unsupported features.
306 if (dwCoInit
!=COINIT_APARTMENTTHREADED
)
308 FIXME(":(%p,%x): unsupported flag %x\n", lpReserved
, (int)dwCoInit
, (int)dwCoInit
);
309 /* Hope for the best and continue anyway */
313 * Check the lock count. If this is the first time going through the initialize
314 * process, we have to initialize the libraries.
316 * And crank-up that lock count.
318 if (InterlockedExchangeAdd(&s_COMLockCount
,1)==0)
321 * Initialize the various COM libraries and data structures.
323 TRACE("() - Initializing the COM libraries\n");
326 RunningObjectTableImpl_Initialize();
336 /***********************************************************************
337 * CoUninitialize [OLE32.47]
339 * This method will release the COM libraries.
341 * See the windows documentation for more details.
343 void WINAPI
CoUninitialize(void)
349 * Decrease the reference count.
350 * If we are back to 0 locks on the COM library, make sure we free
351 * all the associated data structures.
353 lCOMRefCnt
= InterlockedExchangeAdd(&s_COMLockCount
,-1);
357 * Release the various COM libraries and data structures.
359 TRACE("() - Releasing the COM libraries\n");
361 RunningObjectTableImpl_UnInitialize();
363 * Release the references to the registered class objects.
365 COM_RevokeAllClasses();
368 * This will free the loaded COM Dlls.
370 CoFreeAllLibraries();
373 * This will free list of external references to COM objects.
375 COM_ExternalLockFreeList();
378 else if (lCOMRefCnt
<1) {
379 ERR( "CoUninitialize() - not CoInitialized.\n" );
380 InterlockedExchangeAdd(&s_COMLockCount
,1); /* restore the lock count. */
384 /******************************************************************************
385 * CoDisconnectObject [COMPOBJ.15]
386 * CoDisconnectObject [OLE32.8]
388 HRESULT WINAPI
CoDisconnectObject( LPUNKNOWN lpUnk
, DWORD reserved
)
390 TRACE("(%p, %lx)\n",lpUnk
,reserved
);
394 /******************************************************************************
395 * CoCreateGuid[OLE32.6]
398 HRESULT WINAPI
CoCreateGuid(
399 GUID
*pguid
/* [out] points to the GUID to initialize */
401 return UuidCreate(pguid
);
404 /******************************************************************************
405 * CLSIDFromString [OLE32.3]
406 * IIDFromString [OLE32.74]
407 * Converts a unique identifier from its string representation into
411 * If idstr is not a valid CLSID string then it gets treated as a ProgID
416 HRESULT WINAPI
__CLSIDFromStringA(
417 LPCSTR idstr
, /* [in] string representation of guid */
418 CLSID
*id
) /* [out] GUID converted from string */
420 BYTE
*s
= (BYTE
*) idstr
;
425 s
= "{00000000-0000-0000-0000-000000000000}";
426 else { /* validate the CLSID string */
429 return CO_E_CLASSSTRING
;
431 if ((s
[0]!='{') || (s
[9]!='-') || (s
[14]!='-') || (s
[19]!='-') || (s
[24]!='-') || (s
[37]!='}'))
432 return CO_E_CLASSSTRING
;
434 for (i
=1; i
<37; i
++) {
435 if ((i
== 9)||(i
== 14)||(i
== 19)||(i
== 24)) continue;
436 if (!(((s
[i
] >= '0') && (s
[i
] <= '9')) ||
437 ((s
[i
] >= 'a') && (s
[i
] <= 'f')) ||
438 ((s
[i
] >= 'A') && (s
[i
] <= 'F'))))
439 return CO_E_CLASSSTRING
;
443 TRACE("%s -> %p\n", s
, id
);
445 /* quick lookup table */
446 memset(table
, 0, 256);
448 for (i
= 0; i
< 10; i
++) {
451 for (i
= 0; i
< 6; i
++) {
452 table
['A' + i
] = i
+10;
453 table
['a' + i
] = i
+10;
456 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
458 id
->Data1
= (table
[s
[1]] << 28 | table
[s
[2]] << 24 | table
[s
[3]] << 20 | table
[s
[4]] << 16 |
459 table
[s
[5]] << 12 | table
[s
[6]] << 8 | table
[s
[7]] << 4 | table
[s
[8]]);
460 id
->Data2
= table
[s
[10]] << 12 | table
[s
[11]] << 8 | table
[s
[12]] << 4 | table
[s
[13]];
461 id
->Data3
= table
[s
[15]] << 12 | table
[s
[16]] << 8 | table
[s
[17]] << 4 | table
[s
[18]];
463 /* these are just sequential bytes */
464 id
->Data4
[0] = table
[s
[20]] << 4 | table
[s
[21]];
465 id
->Data4
[1] = table
[s
[22]] << 4 | table
[s
[23]];
466 id
->Data4
[2] = table
[s
[25]] << 4 | table
[s
[26]];
467 id
->Data4
[3] = table
[s
[27]] << 4 | table
[s
[28]];
468 id
->Data4
[4] = table
[s
[29]] << 4 | table
[s
[30]];
469 id
->Data4
[5] = table
[s
[31]] << 4 | table
[s
[32]];
470 id
->Data4
[6] = table
[s
[33]] << 4 | table
[s
[34]];
471 id
->Data4
[7] = table
[s
[35]] << 4 | table
[s
[36]];
476 /*****************************************************************************/
478 HRESULT WINAPI
CLSIDFromString(
479 LPCOLESTR idstr
, /* [in] string representation of GUID */
480 CLSID
*id
) /* [out] GUID represented by above string */
485 if (!WideCharToMultiByte( CP_ACP
, 0, idstr
, -1, xid
, sizeof(xid
), NULL
, NULL
))
486 return CO_E_CLASSSTRING
;
489 ret
= __CLSIDFromStringA(xid
,id
);
490 if(ret
!= S_OK
) { /* It appears a ProgID is also valid */
491 ret
= CLSIDFromProgID(idstr
, id
);
496 /******************************************************************************
497 * WINE_StringFromCLSID [Internal]
498 * Converts a GUID into the respective string representation.
503 * the string representation and HRESULT
505 HRESULT
WINE_StringFromCLSID(
506 const CLSID
*id
, /* [in] GUID to be converted */
507 LPSTR idstr
/* [out] pointer to buffer to contain converted guid */
509 static const char *hex
= "0123456789ABCDEF";
514 { ERR("called with id=Null\n");
519 sprintf(idstr
, "{%08lX-%04X-%04X-%02X%02X-",
520 id
->Data1
, id
->Data2
, id
->Data3
,
521 id
->Data4
[0], id
->Data4
[1]);
525 for (i
= 2; i
< 8; i
++) {
526 *s
++ = hex
[id
->Data4
[i
]>>4];
527 *s
++ = hex
[id
->Data4
[i
] & 0xf];
533 TRACE("%p->%s\n", id
, idstr
);
539 /******************************************************************************
540 * StringFromCLSID [OLE32.151]
541 * StringFromIID [OLE32.153]
542 * Converts a GUID into the respective string representation.
543 * The target string is allocated using the OLE IMalloc.
545 * the string representation and HRESULT
547 HRESULT WINAPI
StringFromCLSID(
548 REFCLSID id
, /* [in] the GUID to be converted */
549 LPOLESTR
*idstr
/* [out] a pointer to a to-be-allocated pointer pointing to the resulting string */
555 if ((ret
=CoGetMalloc(0,&mllc
)))
558 ret
=WINE_StringFromCLSID(id
,buf
);
560 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, buf
, -1, NULL
, 0 );
561 *idstr
= IMalloc_Alloc( mllc
, len
* sizeof(WCHAR
) );
562 MultiByteToWideChar( CP_ACP
, 0, buf
, -1, *idstr
, len
);
567 /******************************************************************************
568 * StringFromGUID2 [COMPOBJ.76]
569 * StringFromGUID2 [OLE32.152]
571 * Converts a global unique identifier into a string of an API-
572 * specified fixed format. (The usual {.....} stuff.)
575 * The (UNICODE) string representation of the GUID in 'str'
576 * The length of the resulting string, 0 if there was any problem.
579 StringFromGUID2(REFGUID id
, LPOLESTR str
, INT cmax
)
583 if (WINE_StringFromCLSID(id
,xguid
))
585 return MultiByteToWideChar( CP_ACP
, 0, xguid
, -1, str
, cmax
);
588 /******************************************************************************
589 * ProgIDFromCLSID [OLE32.133]
590 * Converts a class id into the respective Program ID. (By using a registry lookup)
591 * RETURNS S_OK on success
592 * riid associated with the progid
595 HRESULT WINAPI
ProgIDFromCLSID(
596 REFCLSID clsid
, /* [in] class id as found in registry */
597 LPOLESTR
*lplpszProgID
/* [out] associated Prog ID */
600 char strCLSID
[50], *buf
, *buf2
;
606 WINE_StringFromCLSID(clsid
, strCLSID
);
608 buf
= HeapAlloc(GetProcessHeap(), 0, strlen(strCLSID
)+14);
609 sprintf(buf
,"CLSID\\%s\\ProgID", strCLSID
);
610 if (RegOpenKeyA(HKEY_CLASSES_ROOT
, buf
, &xhkey
))
611 ret
= REGDB_E_CLASSNOTREG
;
613 HeapFree(GetProcessHeap(), 0, buf
);
617 buf2
= HeapAlloc(GetProcessHeap(), 0, 255);
619 if (RegQueryValueA(xhkey
, NULL
, buf2
, &buf2len
))
620 ret
= REGDB_E_CLASSNOTREG
;
624 if (CoGetMalloc(0,&mllc
))
628 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, buf2
, -1, NULL
, 0 );
629 *lplpszProgID
= IMalloc_Alloc(mllc
, len
* sizeof(WCHAR
) );
630 MultiByteToWideChar( CP_ACP
, 0, buf2
, -1, *lplpszProgID
, len
);
633 HeapFree(GetProcessHeap(), 0, buf2
);
640 /******************************************************************************
641 * CLSIDFromProgID [OLE32.2]
642 * Converts a program id into the respective GUID. (By using a registry lookup)
644 * riid associated with the progid
646 HRESULT WINAPI
CLSIDFromProgID(
647 LPCOLESTR progid
, /* [in] program id as found in registry */
648 LPCLSID riid
) /* [out] associated CLSID */
650 static const WCHAR clsidW
[] = { '\\','C','L','S','I','D',0 };
652 DWORD buf2len
= sizeof(buf2
);
655 WCHAR
*buf
= HeapAlloc( GetProcessHeap(),0,(strlenW(progid
)+8) * sizeof(WCHAR
) );
656 strcpyW( buf
, progid
);
657 strcatW( buf
, clsidW
);
658 if (RegOpenKeyW(HKEY_CLASSES_ROOT
,buf
,&xhkey
))
660 HeapFree(GetProcessHeap(),0,buf
);
661 return CO_E_CLASSSTRING
;
663 HeapFree(GetProcessHeap(),0,buf
);
665 if (RegQueryValueA(xhkey
,NULL
,buf2
,&buf2len
))
668 return CO_E_CLASSSTRING
;
671 return __CLSIDFromStringA(buf2
,riid
);
676 /*****************************************************************************
677 * CoGetPSClsid [OLE32.22]
679 * This function returns the CLSID of the DLL that implements the proxy and stub
680 * for the specified interface.
682 * It determines this by searching the
683 * HKEY_CLASSES_ROOT\Interface\{string form of riid}\ProxyStubClsid32 in the registry
684 * and any interface id registered by CoRegisterPSClsid within the current process.
686 * FIXME: We only search the registry, not ids registered with CoRegisterPSClsid.
688 HRESULT WINAPI
CoGetPSClsid(
689 REFIID riid
, /* [in] Interface whose proxy/stub CLSID is to be returned */
690 CLSID
*pclsid
) /* [out] Where to store returned proxy/stub CLSID */
696 TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid
), pclsid
);
698 /* Get the input iid as a string */
699 WINE_StringFromCLSID(riid
, buf2
);
700 /* Allocate memory for the registry key we will construct.
701 (length of iid string plus constant length of static text */
702 buf
= HeapAlloc(GetProcessHeap(), 0, strlen(buf2
)+27);
705 return (E_OUTOFMEMORY
);
708 /* Construct the registry key we want */
709 sprintf(buf
,"Interface\\%s\\ProxyStubClsid32", buf2
);
712 if (RegOpenKeyA(HKEY_CLASSES_ROOT
, buf
, &xhkey
))
714 HeapFree(GetProcessHeap(),0,buf
);
715 return (E_INVALIDARG
);
717 HeapFree(GetProcessHeap(),0,buf
);
719 /* ... Once we have the key, query the registry to get the
720 value of CLSID as a string, and convert it into a
721 proper CLSID structure to be passed back to the app */
722 buf2len
= sizeof(buf2
);
723 if ( (RegQueryValueA(xhkey
,NULL
,buf2
,&buf2len
)) )
730 /* We have the CLSid we want back from the registry as a string, so
731 lets convert it into a CLSID structure */
732 if ( (__CLSIDFromStringA(buf2
,pclsid
)) != NOERROR
) {
736 TRACE ("() Returning CLSID=%s\n", debugstr_guid(pclsid
));
742 /***********************************************************************
743 * WriteClassStm (OLE32.159)
745 * This function write a CLSID on stream
747 HRESULT WINAPI
WriteClassStm(IStream
*pStm
,REFCLSID rclsid
)
749 TRACE("(%p,%p)\n",pStm
,rclsid
);
754 return IStream_Write(pStm
,rclsid
,sizeof(CLSID
),NULL
);
757 /***********************************************************************
758 * ReadClassStm (OLE32.135)
760 * This function read a CLSID from a stream
762 HRESULT WINAPI
ReadClassStm(IStream
*pStm
,CLSID
*pclsid
)
767 TRACE("(%p,%p)\n",pStm
,pclsid
);
772 res
= IStream_Read(pStm
,(void*)pclsid
,sizeof(CLSID
),&nbByte
);
777 if (nbByte
!= sizeof(CLSID
))
785 * COM_GetRegisteredClassObject
787 * This internal method is used to scan the registered class list to
788 * find a class object.
791 * rclsid Class ID of the class to find.
792 * dwClsContext Class context to match.
793 * ppv [out] returns a pointer to the class object. Complying
794 * to normal COM usage, this method will increase the
795 * reference count on this object.
797 static HRESULT
COM_GetRegisteredClassObject(
802 HRESULT hr
= S_FALSE
;
803 RegisteredClass
* curClass
;
805 EnterCriticalSection( &csRegisteredClassList
);
813 * Iterate through the whole list and try to match the class ID.
815 curClass
= firstRegisteredClass
;
817 while (curClass
!= 0)
820 * Check if we have a match on the class ID.
822 if (IsEqualGUID(&(curClass
->classIdentifier
), rclsid
))
825 * Since we don't do out-of process or DCOM just right away, let's ignore the
830 * We have a match, return the pointer to the class object.
832 *ppUnk
= curClass
->classObject
;
834 IUnknown_AddRef(curClass
->classObject
);
841 * Step to the next class in the list.
843 curClass
= curClass
->nextClass
;
847 LeaveCriticalSection( &csRegisteredClassList
);
849 * If we get to here, we haven't found our class.
855 _LocalServerThread(LPVOID param
) {
858 RegisteredClass
*newClass
= (RegisteredClass
*)param
;
862 unsigned char *buffer
;
864 IClassFactory
*classfac
;
865 LARGE_INTEGER seekto
;
866 ULARGE_INTEGER newpos
;
869 TRACE("Starting threader for %s.\n",debugstr_guid(&newClass
->classIdentifier
));
870 strcpy(pipefn
,PIPEPREF
);
871 WINE_StringFromCLSID(&newClass
->classIdentifier
,pipefn
+strlen(PIPEPREF
));
873 hres
= IUnknown_QueryInterface(newClass
->classObject
,&IID_IClassFactory
,(LPVOID
*)&classfac
);
874 if (hres
) return hres
;
876 hres
= CreateStreamOnHGlobal(0,TRUE
,&pStm
);
878 FIXME("Failed to create stream on hglobal.\n");
881 hres
= CoMarshalInterface(pStm
,&IID_IClassFactory
,(LPVOID
)classfac
,0,NULL
,0);
883 FIXME("CoMarshalInterface failed, %lx!\n",hres
);
886 hres
= IStream_Stat(pStm
,&ststg
,0);
887 if (hres
) return hres
;
889 buflen
= ststg
.cbSize
.s
.LowPart
;
890 buffer
= HeapAlloc(GetProcessHeap(),0,buflen
);
891 seekto
.s
.LowPart
= 0;
892 seekto
.s
.HighPart
= 0;
893 hres
= IStream_Seek(pStm
,seekto
,SEEK_SET
,&newpos
);
895 FIXME("IStream_Seek failed, %lx\n",hres
);
898 hres
= IStream_Read(pStm
,buffer
,buflen
,&res
);
900 FIXME("Stream Read failed, %lx\n",hres
);
903 IStream_Release(pStm
);
906 hPipe
= CreateNamedPipeA(
909 PIPE_TYPE_BYTE
|PIPE_WAIT
,
910 PIPE_UNLIMITED_INSTANCES
,
913 NMPWAIT_USE_DEFAULT_WAIT
,
916 if (hPipe
== INVALID_HANDLE_VALUE
) {
917 FIXME("pipe creation failed for %s, le is %lx\n",pipefn
,GetLastError());
920 if (!ConnectNamedPipe(hPipe
,NULL
)) {
921 ERR("Failure during ConnectNamedPipe %lx, ABORT!\n",GetLastError());
925 WriteFile(hPipe
,buffer
,buflen
,&res
,NULL
);
931 /******************************************************************************
932 * CoRegisterClassObject [OLE32.36]
934 * This method will register the class object for a given class ID.
936 * See the Windows documentation for more details.
938 HRESULT WINAPI
CoRegisterClassObject(
941 DWORD dwClsContext
, /* [in] CLSCTX flags indicating the context in which to run the executable */
942 DWORD flags
, /* [in] REGCLS flags indicating how connections are made */
946 RegisteredClass
* newClass
;
947 LPUNKNOWN foundObject
;
950 TRACE("(%s,%p,0x%08lx,0x%08lx,%p)\n",
951 debugstr_guid(rclsid
),pUnk
,dwClsContext
,flags
,lpdwRegister
);
953 if ( (lpdwRegister
==0) || (pUnk
==0) )
959 * First, check if the class is already registered.
960 * If it is, this should cause an error.
962 hr
= COM_GetRegisteredClassObject(rclsid
, dwClsContext
, &foundObject
);
964 IUnknown_Release(foundObject
);
965 return CO_E_OBJISREG
;
968 newClass
= HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass
));
969 if ( newClass
== NULL
)
970 return E_OUTOFMEMORY
;
972 EnterCriticalSection( &csRegisteredClassList
);
974 newClass
->classIdentifier
= *rclsid
;
975 newClass
->runContext
= dwClsContext
;
976 newClass
->connectFlags
= flags
;
978 * Use the address of the chain node as the cookie since we are sure it's
981 newClass
->dwCookie
= (DWORD
)newClass
;
982 newClass
->nextClass
= firstRegisteredClass
;
985 * Since we're making a copy of the object pointer, we have to increase its
988 newClass
->classObject
= pUnk
;
989 IUnknown_AddRef(newClass
->classObject
);
991 firstRegisteredClass
= newClass
;
992 LeaveCriticalSection( &csRegisteredClassList
);
994 *lpdwRegister
= newClass
->dwCookie
;
996 if (dwClsContext
& CLSCTX_LOCAL_SERVER
) {
1000 newClass
->hThread
=CreateThread(NULL
,0,_LocalServerThread
,newClass
,0,&tid
);
1005 /***********************************************************************
1006 * CoRevokeClassObject [OLE32.40]
1008 * This method will remove a class object from the class registry
1010 * See the Windows documentation for more details.
1012 HRESULT WINAPI
CoRevokeClassObject(
1015 HRESULT hr
= E_INVALIDARG
;
1016 RegisteredClass
** prevClassLink
;
1017 RegisteredClass
* curClass
;
1019 TRACE("(%08lx)\n",dwRegister
);
1021 EnterCriticalSection( &csRegisteredClassList
);
1024 * Iterate through the whole list and try to match the cookie.
1026 curClass
= firstRegisteredClass
;
1027 prevClassLink
= &firstRegisteredClass
;
1029 while (curClass
!= 0)
1032 * Check if we have a match on the cookie.
1034 if (curClass
->dwCookie
== dwRegister
)
1037 * Remove the class from the chain.
1039 *prevClassLink
= curClass
->nextClass
;
1042 * Release the reference to the class object.
1044 IUnknown_Release(curClass
->classObject
);
1047 * Free the memory used by the chain node.
1049 HeapFree(GetProcessHeap(), 0, curClass
);
1056 * Step to the next class in the list.
1058 prevClassLink
= &(curClass
->nextClass
);
1059 curClass
= curClass
->nextClass
;
1063 LeaveCriticalSection( &csRegisteredClassList
);
1065 * If we get to here, we haven't found our class.
1070 /***********************************************************************
1071 * compobj_RegReadPath [internal]
1073 * Reads a registry value and expands it when nessesary
1075 HRESULT
compobj_RegReadPath(char * keyname
, char * valuename
, char * dst
, int dstlen
)
1081 DWORD dwLength
= dstlen
;
1083 if((hres
= RegOpenKeyExA(HKEY_CLASSES_ROOT
, keyname
, 0, KEY_READ
, &key
)) == ERROR_SUCCESS
) {
1084 if( (hres
= RegQueryValueExA(key
, NULL
, NULL
, &keytype
, (LPBYTE
)src
, &dwLength
)) == ERROR_SUCCESS
) {
1085 if (keytype
== REG_EXPAND_SZ
) {
1086 if (dstlen
<= ExpandEnvironmentStringsA(src
, dst
, dstlen
)) hres
= ERROR_MORE_DATA
;
1088 strncpy(dst
, src
, dstlen
);
1096 /***********************************************************************
1097 * CoGetClassObject [COMPOBJ.7]
1098 * CoGetClassObject [OLE32.16]
1100 * FIXME. If request allows of several options and there is a failure
1101 * with one (other than not being registered) do we try the
1102 * others or return failure? (E.g. inprocess is registered but
1103 * the DLL is not found but the server version works)
1105 HRESULT WINAPI
CoGetClassObject(
1106 REFCLSID rclsid
, DWORD dwClsContext
, COSERVERINFO
*pServerInfo
,
1107 REFIID iid
, LPVOID
*ppv
1109 LPUNKNOWN regClassObject
;
1110 HRESULT hres
= E_UNEXPECTED
;
1113 typedef HRESULT (CALLBACK
*DllGetClassObjectFunc
)(REFCLSID clsid
, REFIID iid
, LPVOID
*ppv
);
1114 DllGetClassObjectFunc DllGetClassObject
;
1116 WINE_StringFromCLSID((LPCLSID
)rclsid
,xclsid
);
1118 TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n", debugstr_guid(rclsid
), debugstr_guid(iid
));
1121 FIXME("\tpServerInfo: name=%s\n",debugstr_w(pServerInfo
->pwszName
));
1122 FIXME("\t\tpAuthInfo=%p\n",pServerInfo
->pAuthInfo
);
1126 * First, try and see if we can't match the class ID with one of the
1127 * registered classes.
1129 if (S_OK
== COM_GetRegisteredClassObject(rclsid
, dwClsContext
, ®ClassObject
))
1132 * Get the required interface from the retrieved pointer.
1134 hres
= IUnknown_QueryInterface(regClassObject
, iid
, ppv
);
1137 * Since QI got another reference on the pointer, we want to release the
1138 * one we already have. If QI was unsuccessful, this will release the object. This
1139 * is good since we are not returning it in the "out" parameter.
1141 IUnknown_Release(regClassObject
);
1146 /* first try: in-process */
1147 if ((CLSCTX_INPROC_SERVER
| CLSCTX_INPROC_HANDLER
) & dwClsContext
) {
1148 char keyname
[MAX_PATH
];
1149 char dllpath
[MAX_PATH
+1];
1151 sprintf(keyname
,"CLSID\\%s\\InprocServer32",xclsid
);
1153 if ( compobj_RegReadPath(keyname
, NULL
, dllpath
, sizeof(dllpath
)) != ERROR_SUCCESS
) {
1154 /* failure: CLSID is not found in registry */
1155 WARN("class %s not registred\n", xclsid
);
1156 hres
= REGDB_E_CLASSNOTREG
;
1158 if ((hLibrary
= LoadLibraryExA(dllpath
, 0, LOAD_WITH_ALTERED_SEARCH_PATH
)) == 0) {
1159 /* failure: DLL could not be loaded */
1160 ERR("couldn't load InprocServer32 dll %s\n", dllpath
);
1161 hres
= E_ACCESSDENIED
; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
1162 } else if (!(DllGetClassObject
= (DllGetClassObjectFunc
)GetProcAddress(hLibrary
, "DllGetClassObject"))) {
1163 /* failure: the dll did not export DllGetClassObject */
1164 ERR("couldn't find function DllGetClassObject in %s\n", dllpath
);
1165 FreeLibrary( hLibrary
);
1166 hres
= CO_E_DLLNOTFOUND
;
1168 /* OK: get the ClassObject */
1169 COMPOBJ_DLLList_Add( hLibrary
);
1170 return DllGetClassObject(rclsid
, iid
, ppv
);
1175 /* Next try out of process */
1176 if (CLSCTX_LOCAL_SERVER
& dwClsContext
)
1178 return create_marshalled_proxy(rclsid
,iid
,ppv
);
1181 /* Finally try remote */
1182 if (CLSCTX_REMOTE_SERVER
& dwClsContext
)
1184 FIXME ("CLSCTX_REMOTE_SERVER not supported\n");
1185 hres
= E_NOINTERFACE
;
1190 /***********************************************************************
1191 * CoResumeClassObjects (OLE32.173)
1193 * Resumes classobjects registered with REGCLS suspended
1195 HRESULT WINAPI
CoResumeClassObjects(void)
1201 /***********************************************************************
1202 * GetClassFile (OLE32.67)
1204 * This function supplies the CLSID associated with the given filename.
1206 HRESULT WINAPI
GetClassFile(LPCOLESTR filePathName
,CLSID
*pclsid
)
1210 int nbElm
, length
, i
;
1212 LPOLESTR
*pathDec
=0,absFile
=0,progId
=0;
1214 static const WCHAR bkslashW
[] = {'\\',0};
1215 static const WCHAR dotW
[] = {'.',0};
1217 TRACE("%s, %p\n", debugstr_w(filePathName
), pclsid
);
1219 /* if the file contain a storage object the return the CLSID writen by IStorage_SetClass method*/
1220 if((StgIsStorageFile(filePathName
))==S_OK
){
1222 res
=StgOpenStorage(filePathName
,NULL
,STGM_READ
| STGM_SHARE_DENY_WRITE
,NULL
,0,&pstg
);
1225 res
=ReadClassStg(pstg
,pclsid
);
1227 IStorage_Release(pstg
);
1231 /* if the file is not a storage object then attemps to match various bits in the file against a
1232 pattern in the registry. this case is not frequently used ! so I present only the psodocode for
1235 for(i=0;i<nFileTypes;i++)
1237 for(i=0;j<nPatternsForType;j++){
1242 pat=ReadPatternFromRegistry(i,j);
1243 hFile=CreateFileW(filePathName,,,,,,hFile);
1244 SetFilePosition(hFile,pat.offset);
1245 ReadFile(hFile,buf,pat.size,NULL,NULL);
1246 if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
1248 *pclsid=ReadCLSIDFromRegistry(i);
1254 /* if the obove strategies fail then search for the extension key in the registry */
1256 /* get the last element (absolute file) in the path name */
1257 nbElm
=FileMonikerImpl_DecomposePath(filePathName
,&pathDec
);
1258 absFile
=pathDec
[nbElm
-1];
1260 /* failed if the path represente a directory and not an absolute file name*/
1261 if (!lstrcmpW(absFile
, bkslashW
))
1262 return MK_E_INVALIDEXTENSION
;
1264 /* get the extension of the file */
1266 length
=lstrlenW(absFile
);
1267 for(i
= length
-1; (i
>= 0) && *(extension
= &absFile
[i
]) != '.'; i
--)
1270 if (!extension
|| !lstrcmpW(extension
, dotW
))
1271 return MK_E_INVALIDEXTENSION
;
1273 res
=RegQueryValueW(HKEY_CLASSES_ROOT
, extension
, NULL
, &sizeProgId
);
1275 /* get the progId associated to the extension */
1276 progId
= CoTaskMemAlloc(sizeProgId
);
1277 res
= RegQueryValueW(HKEY_CLASSES_ROOT
, extension
, progId
, &sizeProgId
);
1279 if (res
==ERROR_SUCCESS
)
1280 /* return the clsid associated to the progId */
1281 res
= CLSIDFromProgID(progId
,pclsid
);
1283 for(i
=0; pathDec
[i
]!=NULL
;i
++)
1284 CoTaskMemFree(pathDec
[i
]);
1285 CoTaskMemFree(pathDec
);
1287 CoTaskMemFree(progId
);
1289 if (res
==ERROR_SUCCESS
)
1292 return MK_E_INVALIDEXTENSION
;
1294 /***********************************************************************
1295 * CoCreateInstance [COMPOBJ.13]
1296 * CoCreateInstance [OLE32.7]
1298 HRESULT WINAPI
CoCreateInstance(
1300 LPUNKNOWN pUnkOuter
,
1306 LPCLASSFACTORY lpclf
= 0;
1315 * Initialize the "out" parameter
1320 * Get a class factory to construct the object we want.
1322 hres
= CoGetClassObject(rclsid
,
1329 FIXME("no classfactory created for CLSID %s, hres is 0x%08lx\n",
1330 debugstr_guid(rclsid
),hres
);
1335 * Create the object and don't forget to release the factory
1337 hres
= IClassFactory_CreateInstance(lpclf
, pUnkOuter
, iid
, ppv
);
1338 IClassFactory_Release(lpclf
);
1340 FIXME("no instance created for interface %s of class %s, hres is 0x%08lx\n",
1341 debugstr_guid(iid
), debugstr_guid(rclsid
),hres
);
1346 /***********************************************************************
1347 * CoCreateInstanceEx [OLE32.165]
1349 HRESULT WINAPI
CoCreateInstanceEx(
1351 LPUNKNOWN pUnkOuter
,
1353 COSERVERINFO
* pServerInfo
,
1357 IUnknown
* pUnk
= NULL
;
1360 int successCount
= 0;
1365 if ( (cmq
==0) || (pResults
==NULL
))
1366 return E_INVALIDARG
;
1368 if (pServerInfo
!=NULL
)
1369 FIXME("() non-NULL pServerInfo not supported!\n");
1372 * Initialize all the "out" parameters.
1374 for (index
= 0; index
< cmq
; index
++)
1376 pResults
[index
].pItf
= NULL
;
1377 pResults
[index
].hr
= E_NOINTERFACE
;
1381 * Get the object and get its IUnknown pointer.
1383 hr
= CoCreateInstance(rclsid
,
1393 * Then, query for all the interfaces requested.
1395 for (index
= 0; index
< cmq
; index
++)
1397 pResults
[index
].hr
= IUnknown_QueryInterface(pUnk
,
1398 pResults
[index
].pIID
,
1399 (VOID
**)&(pResults
[index
].pItf
));
1401 if (pResults
[index
].hr
== S_OK
)
1406 * Release our temporary unknown pointer.
1408 IUnknown_Release(pUnk
);
1410 if (successCount
== 0)
1411 return E_NOINTERFACE
;
1413 if (successCount
!=cmq
)
1414 return CO_S_NOTALLINTERFACES
;
1419 /***********************************************************************
1420 * CoLoadLibrary (OLE32.30)
1422 HINSTANCE WINAPI
CoLoadLibrary(LPOLESTR lpszLibName
, BOOL bAutoFree
)
1424 TRACE("(%s, %d)\n", debugstr_w(lpszLibName
), bAutoFree
);
1426 return LoadLibraryExW(lpszLibName
, 0, LOAD_WITH_ALTERED_SEARCH_PATH
);
1429 /***********************************************************************
1430 * CoFreeLibrary [OLE32.13]
1432 * NOTES: don't belive the docu
1434 void WINAPI
CoFreeLibrary(HINSTANCE hLibrary
)
1436 FreeLibrary(hLibrary
);
1440 /***********************************************************************
1441 * CoFreeAllLibraries [OLE32.12]
1443 * NOTES: don't belive the docu
1445 void WINAPI
CoFreeAllLibraries(void)
1451 /***********************************************************************
1452 * CoFreeUnusedLibraries [COMPOBJ.17]
1453 * CoFreeUnusedLibraries [OLE32.14]
1455 * FIXME: Calls to CoFreeUnusedLibraries from any thread always route
1456 * through the main apartment's thread to call DllCanUnloadNow
1458 void WINAPI
CoFreeUnusedLibraries(void)
1460 COMPOBJ_DllList_FreeUnused(0);
1463 /***********************************************************************
1464 * CoFileTimeNow [COMPOBJ.82]
1465 * CoFileTimeNow [OLE32.10]
1468 * the current system time in lpFileTime
1470 HRESULT WINAPI
CoFileTimeNow( FILETIME
*lpFileTime
) /* [out] the current time */
1472 GetSystemTimeAsFileTime( lpFileTime
);
1476 /***********************************************************************
1477 * CoLoadLibrary (OLE32.30)
1479 static void COM_RevokeAllClasses()
1481 EnterCriticalSection( &csRegisteredClassList
);
1483 while (firstRegisteredClass
!=0)
1485 CoRevokeClassObject(firstRegisteredClass
->dwCookie
);
1488 LeaveCriticalSection( &csRegisteredClassList
);
1491 /****************************************************************************
1492 * COM External Lock methods implementation
1494 * This api provides a linked list to managed external references to
1497 * The public interface consists of three calls:
1498 * COM_ExternalLockAddRef
1499 * COM_ExternalLockRelease
1500 * COM_ExternalLockFreeList
1503 #define EL_END_OF_LIST 0
1504 #define EL_NOT_FOUND 0
1507 * Declaration of the static structure that manage the
1508 * external lock to COM objects.
1510 typedef struct COM_ExternalLock COM_ExternalLock
;
1511 typedef struct COM_ExternalLockList COM_ExternalLockList
;
1513 struct COM_ExternalLock
1515 IUnknown
*pUnk
; /* IUnknown referenced */
1516 ULONG uRefCount
; /* external lock counter to IUnknown object*/
1517 COM_ExternalLock
*next
; /* Pointer to next element in list */
1520 struct COM_ExternalLockList
1522 COM_ExternalLock
*head
; /* head of list */
1526 * Declaration and initialization of the static structure that manages
1527 * the external lock to COM objects.
1529 static COM_ExternalLockList elList
= { EL_END_OF_LIST
};
1532 * Private methods used to managed the linked list
1536 static COM_ExternalLock
* COM_ExternalLockLocate(
1537 COM_ExternalLock
*element
,
1540 /****************************************************************************
1541 * Internal - Insert a new IUnknown* to the linked list
1543 static BOOL
COM_ExternalLockInsert(
1546 COM_ExternalLock
*newLock
= NULL
;
1547 COM_ExternalLock
*previousHead
= NULL
;
1550 * Allocate space for the new storage object
1552 newLock
= HeapAlloc(GetProcessHeap(), 0, sizeof(COM_ExternalLock
));
1554 if (newLock
!=NULL
) {
1555 if ( elList
.head
== EL_END_OF_LIST
) {
1556 elList
.head
= newLock
; /* The list is empty */
1558 /* insert does it at the head */
1559 previousHead
= elList
.head
;
1560 elList
.head
= newLock
;
1563 /* Set new list item data member */
1564 newLock
->pUnk
= pUnk
;
1565 newLock
->uRefCount
= 1;
1566 newLock
->next
= previousHead
;
1573 /****************************************************************************
1574 * Internal - Method that removes an item from the linked list.
1576 static void COM_ExternalLockDelete(
1577 COM_ExternalLock
*itemList
)
1579 COM_ExternalLock
*current
= elList
.head
;
1581 if ( current
== itemList
) {
1582 /* this section handles the deletion of the first node */
1583 elList
.head
= itemList
->next
;
1584 HeapFree( GetProcessHeap(), 0, itemList
);
1587 if ( current
->next
== itemList
){ /* We found the item to free */
1588 current
->next
= itemList
->next
; /* readjust the list pointers */
1589 HeapFree( GetProcessHeap(), 0, itemList
);
1593 /* Skip to the next item */
1594 current
= current
->next
;
1596 } while ( current
!= EL_END_OF_LIST
);
1600 /****************************************************************************
1601 * Internal - Recursivity agent for IUnknownExternalLockList_Find
1603 * NOTES: how long can the list be ?? (recursive!!!)
1605 static COM_ExternalLock
* COM_ExternalLockLocate( COM_ExternalLock
*element
, IUnknown
*pUnk
)
1607 if ( element
== EL_END_OF_LIST
)
1608 return EL_NOT_FOUND
;
1609 else if ( element
->pUnk
== pUnk
) /* We found it */
1611 else /* Not the right guy, keep on looking */
1612 return COM_ExternalLockLocate( element
->next
, pUnk
);
1615 /****************************************************************************
1616 * Public - Method that increments the count for a IUnknown* in the linked
1617 * list. The item is inserted if not already in the list.
1619 static void COM_ExternalLockAddRef(IUnknown
*pUnk
)
1621 COM_ExternalLock
*externalLock
= COM_ExternalLockLocate(elList
.head
, pUnk
);
1624 * Add an external lock to the object. If it was already externally
1625 * locked, just increase the reference count. If it was not.
1626 * add the item to the list.
1628 if ( externalLock
== EL_NOT_FOUND
)
1629 COM_ExternalLockInsert(pUnk
);
1631 externalLock
->uRefCount
++;
1634 * Add an internal lock to the object
1636 IUnknown_AddRef(pUnk
);
1639 /****************************************************************************
1640 * Public - Method that decrements the count for a IUnknown* in the linked
1641 * list. The item is removed from the list if its count end up at zero or if
1644 static void COM_ExternalLockRelease(
1648 COM_ExternalLock
*externalLock
= COM_ExternalLockLocate(elList
.head
, pUnk
);
1650 if ( externalLock
!= EL_NOT_FOUND
) {
1652 externalLock
->uRefCount
--; /* release external locks */
1653 IUnknown_Release(pUnk
); /* release local locks as well */
1655 if ( bRelAll
== FALSE
) break; /* perform single release */
1657 } while ( externalLock
->uRefCount
> 0 );
1659 if ( externalLock
->uRefCount
== 0 ) /* get rid of the list entry */
1660 COM_ExternalLockDelete(externalLock
);
1663 /****************************************************************************
1664 * Public - Method that frees the content of the list.
1666 static void COM_ExternalLockFreeList()
1668 COM_ExternalLock
*head
;
1670 head
= elList
.head
; /* grab it by the head */
1671 while ( head
!= EL_END_OF_LIST
) {
1672 COM_ExternalLockDelete(head
); /* get rid of the head stuff */
1673 head
= elList
.head
; /* get the new head... */
1677 /****************************************************************************
1678 * Public - Method that dump the content of the list.
1680 void COM_ExternalLockDump()
1682 COM_ExternalLock
*current
= elList
.head
;
1684 DPRINTF("\nExternal lock list contains:\n");
1686 while ( current
!= EL_END_OF_LIST
) {
1687 DPRINTF( "\t%p with %lu references count.\n", current
->pUnk
, current
->uRefCount
);
1689 /* Skip to the next item */
1690 current
= current
->next
;
1694 /******************************************************************************
1695 * CoLockObjectExternal [OLE32.31]
1697 HRESULT WINAPI
CoLockObjectExternal(
1698 LPUNKNOWN pUnk
, /* [in] object to be locked */
1699 BOOL fLock
, /* [in] do lock */
1700 BOOL fLastUnlockReleases
) /* [in] unlock all */
1705 * Increment the external lock coutner, COM_ExternalLockAddRef also
1706 * increment the object's internal lock counter.
1708 COM_ExternalLockAddRef( pUnk
);
1711 * Decrement the external lock coutner, COM_ExternalLockRelease also
1712 * decrement the object's internal lock counter.
1714 COM_ExternalLockRelease( pUnk
, fLastUnlockReleases
);
1720 /***********************************************************************
1721 * CoInitializeWOW (OLE32.27)
1723 HRESULT WINAPI
CoInitializeWOW(DWORD x
,DWORD y
) {
1724 FIXME("(0x%08lx,0x%08lx),stub!\n",x
,y
);
1728 static IUnknown
* pUnkState
= 0; /* FIXME: thread local */
1729 static int nStatCounter
= 0; /* global */
1730 static HMODULE hOleAut32
= 0; /* global */
1732 /***********************************************************************
1733 * CoGetState [OLE32.24]
1735 * NOTES: might be incomplete
1737 HRESULT WINAPI
CoGetState(IUnknown
** ppv
)
1742 IUnknown_AddRef(pUnkState
);
1744 FIXME("-- %p\n", *ppv
);
1752 /***********************************************************************
1753 * CoSetState [OLE32.42]
1755 * NOTES: FIXME: protect this with a crst
1757 HRESULT WINAPI
CoSetState(IUnknown
* pv
)
1759 FIXME("(%p),stub!\n", pv
);
1762 IUnknown_AddRef(pv
);
1764 if (nStatCounter
== 1) LoadLibraryA("OLEAUT32.DLL");
1768 TRACE("-- release %p now\n", pUnkState
);
1769 IUnknown_Release(pUnkState
);
1771 if (!nStatCounter
) FreeLibrary(hOleAut32
);
1778 /******************************************************************************
1779 * OleGetAutoConvert [OLE32.104]
1781 HRESULT WINAPI
OleGetAutoConvert(REFCLSID clsidOld
, LPCLSID pClsidNew
)
1789 sprintf(buf
,"CLSID\\");WINE_StringFromCLSID(clsidOld
,&buf
[6]);
1790 if (RegOpenKeyA(HKEY_CLASSES_ROOT
,buf
,&hkey
))
1792 res
= REGDB_E_CLASSNOTREG
;
1796 /* we can just query for the default value of AutoConvertTo key like that,
1797 without opening the AutoConvertTo key and querying for NULL (default) */
1798 if (RegQueryValueA(hkey
,"AutoConvertTo",buf
,&len
))
1800 res
= REGDB_E_KEYMISSING
;
1803 MultiByteToWideChar( CP_ACP
, 0, buf
, -1, wbuf
, sizeof(wbuf
)/sizeof(WCHAR
) );
1804 CLSIDFromString(wbuf
,pClsidNew
);
1806 if (hkey
) RegCloseKey(hkey
);
1810 /******************************************************************************
1811 * OleSetAutoConvert [OLE32.126]
1813 HRESULT WINAPI
OleSetAutoConvert(REFCLSID clsidOld
, REFCLSID clsidNew
)
1816 char buf
[200], szClsidNew
[200];
1819 TRACE("(%s,%s)\n", debugstr_guid(clsidOld
), debugstr_guid(clsidNew
));
1820 sprintf(buf
,"CLSID\\");WINE_StringFromCLSID(clsidOld
,&buf
[6]);
1821 WINE_StringFromCLSID(clsidNew
, szClsidNew
);
1822 if (RegOpenKeyA(HKEY_CLASSES_ROOT
,buf
,&hkey
))
1824 res
= REGDB_E_CLASSNOTREG
;
1827 if (RegSetValueA(hkey
, "AutoConvertTo", REG_SZ
, szClsidNew
, strlen(szClsidNew
)+1))
1829 res
= REGDB_E_WRITEREGDB
;
1834 if (hkey
) RegCloseKey(hkey
);
1838 /******************************************************************************
1839 * CoTreatAsClass [OLE32.46]
1841 HRESULT WINAPI
CoTreatAsClass(REFCLSID clsidOld
, REFCLSID clsidNew
)
1844 char buf
[200], szClsidNew
[200];
1847 FIXME("(%s,%s)\n", debugstr_guid(clsidOld
), debugstr_guid(clsidNew
));
1848 sprintf(buf
,"CLSID\\");WINE_StringFromCLSID(clsidOld
,&buf
[6]);
1849 WINE_StringFromCLSID(clsidNew
, szClsidNew
);
1850 if (RegOpenKeyA(HKEY_CLASSES_ROOT
,buf
,&hkey
))
1852 res
= REGDB_E_CLASSNOTREG
;
1855 if (RegSetValueA(hkey
, "AutoTreatAs", REG_SZ
, szClsidNew
, strlen(szClsidNew
)+1))
1857 res
= REGDB_E_WRITEREGDB
;
1862 if (hkey
) RegCloseKey(hkey
);
1867 /***********************************************************************
1868 * IsEqualGUID [OLE32.76]
1870 * Compares two Unique Identifiers.
1876 BOOL WINAPI
IsEqualGUID(
1877 REFGUID rguid1
, /* [in] unique id 1 */
1878 REFGUID rguid2
/* [in] unique id 2 */
1881 return !memcmp(rguid1
,rguid2
,sizeof(GUID
));
1884 /***********************************************************************
1885 * CoInitializeSecurity [OLE32.164]
1887 HRESULT WINAPI
CoInitializeSecurity(PSECURITY_DESCRIPTOR pSecDesc
, LONG cAuthSvc
,
1888 SOLE_AUTHENTICATION_SERVICE
* asAuthSvc
,
1889 void* pReserved1
, DWORD dwAuthnLevel
,
1890 DWORD dwImpLevel
, void* pReserved2
,
1891 DWORD dwCapabilities
, void* pReserved3
)
1893 FIXME("(%p,%ld,%p,%p,%ld,%ld,%p,%ld,%p) - stub!\n", pSecDesc
, cAuthSvc
,
1894 asAuthSvc
, pReserved1
, dwAuthnLevel
, dwImpLevel
, pReserved2
,
1895 dwCapabilities
, pReserved3
);