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
40 #include "wine/unicode.h"
42 #include "compobj_private.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
48 /****************************************************************************
49 * This section defines variables internal to the COM module.
51 * TODO: Most of these things will have to be made thread-safe.
53 HINSTANCE COMPOBJ_hInstance32
= 0;
55 static HRESULT
COM_GetRegisteredClassObject(REFCLSID rclsid
, DWORD dwClsContext
, LPUNKNOWN
* ppUnk
);
56 static void COM_RevokeAllClasses();
57 static void COM_ExternalLockFreeList();
59 /*****************************************************************************
60 * Appartment management stuff
63 * per Thread values are stored in the TEB on offset 0xF80
65 * see www.microsoft.com/msj/1099/bugslayer/bugslayer1099.htm
70 unsigned char threadingModell
; /* we use the COINIT flags */
71 unsigned long threadID
;
72 long AppartmentLockCount
;
76 OleAppartmentData
*AppartmentData
;
80 static CRITICAL_SECTION csAppartmentData = CRITICAL_SECTION_INIT("csAppartmentData");
83 * the first STA created in a process is the main STA
87 static OleAppartmentData * mainSTA;
91 * a Process can only have one MTA
95 static OleAppartmentData * processMTA;
100 * This lock count counts the number of times CoInitialize is called. It is
101 * decreased every time CoUninitialize is called. When it hits 0, the COM
102 * libraries are freed
104 static LONG s_COMLockCount
= 0;
107 * This linked list contains the list of registered class objects. These
108 * are mostly used to register the factories for out-of-proc servers of OLE
111 * TODO: Make this data structure aware of inter-process communication. This
112 * means that parts of this will be exported to the Wine Server.
114 typedef struct tagRegisteredClass
116 CLSID classIdentifier
;
117 LPUNKNOWN classObject
;
121 HANDLE hThread
; /* only for localserver */
122 struct tagRegisteredClass
* nextClass
;
125 static CRITICAL_SECTION csRegisteredClassList
= CRITICAL_SECTION_INIT("csRegisteredClassList");
126 static RegisteredClass
* firstRegisteredClass
= NULL
;
128 /*****************************************************************************
129 * This section contains OpenDllList definitions
131 * The OpenDllList contains only handles of dll loaded by CoGetClassObject or
132 * other functions what do LoadLibrary _without_ giving back a HMODULE.
133 * Without this list these handles would be freed never.
135 * FIXME: a DLL what says OK whenn asked for unloading is unloaded in the
136 * next unload-call but not before 600 sec.
139 typedef struct tagOpenDll
{
141 struct tagOpenDll
*next
;
144 static CRITICAL_SECTION csOpenDllList
= CRITICAL_SECTION_INIT("csOpenDllList");
145 static OpenDll
*openDllList
= NULL
; /* linked list of open dlls */
147 static void COMPOBJ_DLLList_Add(HANDLE hLibrary
);
148 static void COMPOBJ_DllList_FreeUnused(int Timeout
);
151 /******************************************************************************
152 * Initialize/Uninitialize critical sections.
154 void COMPOBJ_InitProcess( void )
158 void COMPOBJ_UninitProcess( void )
162 /*****************************************************************************
163 * This section contains OpenDllList implemantation
166 static void COMPOBJ_DLLList_Add(HANDLE hLibrary
)
173 EnterCriticalSection( &csOpenDllList
);
175 if (openDllList
== NULL
) {
176 /* empty list -- add first node */
177 openDllList
= (OpenDll
*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll
));
178 openDllList
->hLibrary
=hLibrary
;
179 openDllList
->next
= NULL
;
181 /* search for this dll */
183 for (ptr
= openDllList
; ptr
->next
!= NULL
; ptr
=ptr
->next
) {
184 if (ptr
->hLibrary
== hLibrary
) {
190 /* dll not found, add it */
192 openDllList
= (OpenDll
*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll
));
193 openDllList
->hLibrary
= hLibrary
;
194 openDllList
->next
= tmp
;
198 LeaveCriticalSection( &csOpenDllList
);
201 static void COMPOBJ_DllList_FreeUnused(int Timeout
)
203 OpenDll
*curr
, *next
, *prev
= NULL
;
204 typedef HRESULT(*DllCanUnloadNowFunc
)(void);
205 DllCanUnloadNowFunc DllCanUnloadNow
;
209 EnterCriticalSection( &csOpenDllList
);
211 for (curr
= openDllList
; curr
!= NULL
; ) {
212 DllCanUnloadNow
= (DllCanUnloadNowFunc
) GetProcAddress(curr
->hLibrary
, "DllCanUnloadNow");
214 if ( (DllCanUnloadNow
!= NULL
) && (DllCanUnloadNow() == S_OK
) ) {
217 TRACE("freeing %p\n", curr
->hLibrary
);
218 FreeLibrary(curr
->hLibrary
);
220 HeapFree(GetProcessHeap(), 0, curr
);
221 if (curr
== openDllList
) {
234 LeaveCriticalSection( &csOpenDllList
);
237 /******************************************************************************
238 * CoBuildVersion [COMPOBJ.1]
239 * CoBuildVersion [OLE32.4]
242 * Current build version, hiword is majornumber, loword is minornumber
244 DWORD WINAPI
CoBuildVersion(void)
246 TRACE("Returning version %d, build %d.\n", rmm
, rup
);
247 return (rmm
<<16)+rup
;
250 /******************************************************************************
251 * CoInitialize [OLE32.26]
253 * Initializes the COM libraries.
257 HRESULT WINAPI
CoInitialize(
258 LPVOID lpReserved
/* [in] pointer to win32 malloc interface
259 (obsolete, should be NULL) */
263 * Just delegate to the newer method.
265 return CoInitializeEx(lpReserved
, COINIT_APARTMENTTHREADED
);
268 /******************************************************************************
269 * CoInitializeEx [OLE32.163]
271 * Initializes the COM libraries. The behavior used to set the win32 IMalloc
272 * used for memory management is obsolete.
275 * S_OK if successful,
276 * S_FALSE if this function was called already.
277 * RPC_E_CHANGED_MODE if a previous call to CoInitialize specified another
281 * Only the single threaded model is supported. As a result RPC_E_CHANGED_MODE
284 * See the windows documentation for more details.
286 HRESULT WINAPI
CoInitializeEx(
287 LPVOID lpReserved
, /* [in] pointer to win32 malloc interface
288 (obsolete, should be NULL) */
289 DWORD dwCoInit
/* [in] A value from COINIT specifies the threading model */
294 TRACE("(%p, %x)\n", lpReserved
, (int)dwCoInit
);
296 if (lpReserved
!=NULL
)
298 ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved
, (int)dwCoInit
, lpReserved
);
302 * Check for unsupported features.
304 if (dwCoInit
!=COINIT_APARTMENTTHREADED
)
306 FIXME(":(%p,%x): unsupported flag %x\n", lpReserved
, (int)dwCoInit
, (int)dwCoInit
);
307 /* Hope for the best and continue anyway */
311 * Check the lock count. If this is the first time going through the initialize
312 * process, we have to initialize the libraries.
314 * And crank-up that lock count.
316 if (InterlockedExchangeAdd(&s_COMLockCount
,1)==0)
319 * Initialize the various COM libraries and data structures.
321 TRACE("() - Initializing the COM libraries\n");
324 RunningObjectTableImpl_Initialize();
334 /***********************************************************************
335 * CoUninitialize [OLE32.47]
337 * This method will release the COM libraries.
339 * See the windows documentation for more details.
341 void WINAPI
CoUninitialize(void)
347 * Decrease the reference count.
348 * If we are back to 0 locks on the COM library, make sure we free
349 * all the associated data structures.
351 lCOMRefCnt
= InterlockedExchangeAdd(&s_COMLockCount
,-1);
355 * Release the various COM libraries and data structures.
357 TRACE("() - Releasing the COM libraries\n");
359 RunningObjectTableImpl_UnInitialize();
361 * Release the references to the registered class objects.
363 COM_RevokeAllClasses();
366 * This will free the loaded COM Dlls.
368 CoFreeAllLibraries();
371 * This will free list of external references to COM objects.
373 COM_ExternalLockFreeList();
376 else if (lCOMRefCnt
<1) {
377 ERR( "CoUninitialize() - not CoInitialized.\n" );
378 InterlockedExchangeAdd(&s_COMLockCount
,1); /* restore the lock count. */
382 /******************************************************************************
383 * CoDisconnectObject [COMPOBJ.15]
384 * CoDisconnectObject [OLE32.8]
386 HRESULT WINAPI
CoDisconnectObject( LPUNKNOWN lpUnk
, DWORD reserved
)
388 TRACE("(%p, %lx)\n",lpUnk
,reserved
);
392 /******************************************************************************
393 * CoCreateGuid[OLE32.6]
396 HRESULT WINAPI
CoCreateGuid(
397 GUID
*pguid
/* [out] points to the GUID to initialize */
399 return UuidCreate(pguid
);
402 /******************************************************************************
403 * CLSIDFromString [OLE32.3]
404 * IIDFromString [OLE32.74]
405 * Converts a unique identifier from its string representation into
409 * If idstr is not a valid CLSID string then it gets treated as a ProgID
414 HRESULT WINAPI
__CLSIDFromStringA(
415 LPCSTR idstr
, /* [in] string representation of guid */
416 CLSID
*id
) /* [out] GUID converted from string */
418 BYTE
*s
= (BYTE
*) idstr
;
423 s
= "{00000000-0000-0000-0000-000000000000}";
424 else { /* validate the CLSID string */
427 return CO_E_CLASSSTRING
;
429 if ((s
[0]!='{') || (s
[9]!='-') || (s
[14]!='-') || (s
[19]!='-') || (s
[24]!='-') || (s
[37]!='}'))
430 return CO_E_CLASSSTRING
;
432 for (i
=1; i
<37; i
++) {
433 if ((i
== 9)||(i
== 14)||(i
== 19)||(i
== 24)) continue;
434 if (!(((s
[i
] >= '0') && (s
[i
] <= '9')) ||
435 ((s
[i
] >= 'a') && (s
[i
] <= 'f')) ||
436 ((s
[i
] >= 'A') && (s
[i
] <= 'F'))))
437 return CO_E_CLASSSTRING
;
441 TRACE("%s -> %p\n", s
, id
);
443 /* quick lookup table */
444 memset(table
, 0, 256);
446 for (i
= 0; i
< 10; i
++) {
449 for (i
= 0; i
< 6; i
++) {
450 table
['A' + i
] = i
+10;
451 table
['a' + i
] = i
+10;
454 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
456 id
->Data1
= (table
[s
[1]] << 28 | table
[s
[2]] << 24 | table
[s
[3]] << 20 | table
[s
[4]] << 16 |
457 table
[s
[5]] << 12 | table
[s
[6]] << 8 | table
[s
[7]] << 4 | table
[s
[8]]);
458 id
->Data2
= table
[s
[10]] << 12 | table
[s
[11]] << 8 | table
[s
[12]] << 4 | table
[s
[13]];
459 id
->Data3
= table
[s
[15]] << 12 | table
[s
[16]] << 8 | table
[s
[17]] << 4 | table
[s
[18]];
461 /* these are just sequential bytes */
462 id
->Data4
[0] = table
[s
[20]] << 4 | table
[s
[21]];
463 id
->Data4
[1] = table
[s
[22]] << 4 | table
[s
[23]];
464 id
->Data4
[2] = table
[s
[25]] << 4 | table
[s
[26]];
465 id
->Data4
[3] = table
[s
[27]] << 4 | table
[s
[28]];
466 id
->Data4
[4] = table
[s
[29]] << 4 | table
[s
[30]];
467 id
->Data4
[5] = table
[s
[31]] << 4 | table
[s
[32]];
468 id
->Data4
[6] = table
[s
[33]] << 4 | table
[s
[34]];
469 id
->Data4
[7] = table
[s
[35]] << 4 | table
[s
[36]];
474 /*****************************************************************************/
476 HRESULT WINAPI
CLSIDFromString(
477 LPCOLESTR idstr
, /* [in] string representation of GUID */
478 CLSID
*id
) /* [out] GUID represented by above string */
483 if (!WideCharToMultiByte( CP_ACP
, 0, idstr
, -1, xid
, sizeof(xid
), NULL
, NULL
))
484 return CO_E_CLASSSTRING
;
487 ret
= __CLSIDFromStringA(xid
,id
);
488 if(ret
!= S_OK
) { /* It appears a ProgID is also valid */
489 ret
= CLSIDFromProgID(idstr
, id
);
494 /******************************************************************************
495 * WINE_StringFromCLSID [Internal]
496 * Converts a GUID into the respective string representation.
501 * the string representation and HRESULT
503 HRESULT
WINE_StringFromCLSID(
504 const CLSID
*id
, /* [in] GUID to be converted */
505 LPSTR idstr
/* [out] pointer to buffer to contain converted guid */
507 static const char *hex
= "0123456789ABCDEF";
512 { ERR("called with id=Null\n");
517 sprintf(idstr
, "{%08lX-%04X-%04X-%02X%02X-",
518 id
->Data1
, id
->Data2
, id
->Data3
,
519 id
->Data4
[0], id
->Data4
[1]);
523 for (i
= 2; i
< 8; i
++) {
524 *s
++ = hex
[id
->Data4
[i
]>>4];
525 *s
++ = hex
[id
->Data4
[i
] & 0xf];
531 TRACE("%p->%s\n", id
, idstr
);
537 /******************************************************************************
538 * StringFromCLSID [OLE32.151]
539 * StringFromIID [OLE32.153]
540 * Converts a GUID into the respective string representation.
541 * The target string is allocated using the OLE IMalloc.
543 * the string representation and HRESULT
545 HRESULT WINAPI
StringFromCLSID(
546 REFCLSID id
, /* [in] the GUID to be converted */
547 LPOLESTR
*idstr
/* [out] a pointer to a to-be-allocated pointer pointing to the resulting string */
553 if ((ret
=CoGetMalloc(0,&mllc
)))
556 ret
=WINE_StringFromCLSID(id
,buf
);
558 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, buf
, -1, NULL
, 0 );
559 *idstr
= IMalloc_Alloc( mllc
, len
* sizeof(WCHAR
) );
560 MultiByteToWideChar( CP_ACP
, 0, buf
, -1, *idstr
, len
);
565 /******************************************************************************
566 * StringFromGUID2 [COMPOBJ.76]
567 * StringFromGUID2 [OLE32.152]
569 * Converts a global unique identifier into a string of an API-
570 * specified fixed format. (The usual {.....} stuff.)
573 * The (UNICODE) string representation of the GUID in 'str'
574 * The length of the resulting string, 0 if there was any problem.
577 StringFromGUID2(REFGUID id
, LPOLESTR str
, INT cmax
)
581 if (WINE_StringFromCLSID(id
,xguid
))
583 return MultiByteToWideChar( CP_ACP
, 0, xguid
, -1, str
, cmax
);
586 /******************************************************************************
587 * ProgIDFromCLSID [OLE32.133]
588 * Converts a class id into the respective Program ID. (By using a registry lookup)
589 * RETURNS S_OK on success
590 * riid associated with the progid
593 HRESULT WINAPI
ProgIDFromCLSID(
594 REFCLSID clsid
, /* [in] class id as found in registry */
595 LPOLESTR
*lplpszProgID
/* [out] associated Prog ID */
598 char strCLSID
[50], *buf
, *buf2
;
604 WINE_StringFromCLSID(clsid
, strCLSID
);
606 buf
= HeapAlloc(GetProcessHeap(), 0, strlen(strCLSID
)+14);
607 sprintf(buf
,"CLSID\\%s\\ProgID", strCLSID
);
608 if (RegOpenKeyA(HKEY_CLASSES_ROOT
, buf
, &xhkey
))
609 ret
= REGDB_E_CLASSNOTREG
;
611 HeapFree(GetProcessHeap(), 0, buf
);
615 buf2
= HeapAlloc(GetProcessHeap(), 0, 255);
617 if (RegQueryValueA(xhkey
, NULL
, buf2
, &buf2len
))
618 ret
= REGDB_E_CLASSNOTREG
;
622 if (CoGetMalloc(0,&mllc
))
626 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, buf2
, -1, NULL
, 0 );
627 *lplpszProgID
= IMalloc_Alloc(mllc
, len
* sizeof(WCHAR
) );
628 MultiByteToWideChar( CP_ACP
, 0, buf2
, -1, *lplpszProgID
, len
);
631 HeapFree(GetProcessHeap(), 0, buf2
);
638 /******************************************************************************
639 * CLSIDFromProgID [OLE32.2]
640 * Converts a program id into the respective GUID. (By using a registry lookup)
642 * riid associated with the progid
644 HRESULT WINAPI
CLSIDFromProgID(
645 LPCOLESTR progid
, /* [in] program id as found in registry */
646 LPCLSID riid
) /* [out] associated CLSID */
648 static const WCHAR clsidW
[] = { '\\','C','L','S','I','D',0 };
650 DWORD buf2len
= sizeof(buf2
);
653 WCHAR
*buf
= HeapAlloc( GetProcessHeap(),0,(strlenW(progid
)+8) * sizeof(WCHAR
) );
654 strcpyW( buf
, progid
);
655 strcatW( buf
, clsidW
);
656 if (RegOpenKeyW(HKEY_CLASSES_ROOT
,buf
,&xhkey
))
658 HeapFree(GetProcessHeap(),0,buf
);
659 return CO_E_CLASSSTRING
;
661 HeapFree(GetProcessHeap(),0,buf
);
663 if (RegQueryValueA(xhkey
,NULL
,buf2
,&buf2len
))
666 return CO_E_CLASSSTRING
;
669 return __CLSIDFromStringA(buf2
,riid
);
674 /*****************************************************************************
675 * CoGetPSClsid [OLE32.22]
677 * This function returns the CLSID of the DLL that implements the proxy and stub
678 * for the specified interface.
680 * It determines this by searching the
681 * HKEY_CLASSES_ROOT\Interface\{string form of riid}\ProxyStubClsid32 in the registry
682 * and any interface id registered by CoRegisterPSClsid within the current process.
684 * FIXME: We only search the registry, not ids registered with CoRegisterPSClsid.
686 HRESULT WINAPI
CoGetPSClsid(
687 REFIID riid
, /* [in] Interface whose proxy/stub CLSID is to be returned */
688 CLSID
*pclsid
) /* [out] Where to store returned proxy/stub CLSID */
694 TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid
), pclsid
);
696 /* Get the input iid as a string */
697 WINE_StringFromCLSID(riid
, buf2
);
698 /* Allocate memory for the registry key we will construct.
699 (length of iid string plus constant length of static text */
700 buf
= HeapAlloc(GetProcessHeap(), 0, strlen(buf2
)+27);
703 return (E_OUTOFMEMORY
);
706 /* Construct the registry key we want */
707 sprintf(buf
,"Interface\\%s\\ProxyStubClsid32", buf2
);
710 if (RegOpenKeyA(HKEY_CLASSES_ROOT
, buf
, &xhkey
))
712 HeapFree(GetProcessHeap(),0,buf
);
713 return (E_INVALIDARG
);
715 HeapFree(GetProcessHeap(),0,buf
);
717 /* ... Once we have the key, query the registry to get the
718 value of CLSID as a string, and convert it into a
719 proper CLSID structure to be passed back to the app */
720 buf2len
= sizeof(buf2
);
721 if ( (RegQueryValueA(xhkey
,NULL
,buf2
,&buf2len
)) )
728 /* We have the CLSid we want back from the registry as a string, so
729 lets convert it into a CLSID structure */
730 if ( (__CLSIDFromStringA(buf2
,pclsid
)) != NOERROR
) {
734 TRACE ("() Returning CLSID=%s\n", debugstr_guid(pclsid
));
740 /***********************************************************************
741 * WriteClassStm (OLE32.159)
743 * This function write a CLSID on stream
745 HRESULT WINAPI
WriteClassStm(IStream
*pStm
,REFCLSID rclsid
)
747 TRACE("(%p,%p)\n",pStm
,rclsid
);
752 return IStream_Write(pStm
,rclsid
,sizeof(CLSID
),NULL
);
755 /***********************************************************************
756 * ReadClassStm (OLE32.135)
758 * This function read a CLSID from a stream
760 HRESULT WINAPI
ReadClassStm(IStream
*pStm
,CLSID
*pclsid
)
765 TRACE("(%p,%p)\n",pStm
,pclsid
);
770 res
= IStream_Read(pStm
,(void*)pclsid
,sizeof(CLSID
),&nbByte
);
775 if (nbByte
!= sizeof(CLSID
))
783 * COM_GetRegisteredClassObject
785 * This internal method is used to scan the registered class list to
786 * find a class object.
789 * rclsid Class ID of the class to find.
790 * dwClsContext Class context to match.
791 * ppv [out] returns a pointer to the class object. Complying
792 * to normal COM usage, this method will increase the
793 * reference count on this object.
795 static HRESULT
COM_GetRegisteredClassObject(
800 HRESULT hr
= S_FALSE
;
801 RegisteredClass
* curClass
;
803 EnterCriticalSection( &csRegisteredClassList
);
811 * Iterate through the whole list and try to match the class ID.
813 curClass
= firstRegisteredClass
;
815 while (curClass
!= 0)
818 * Check if we have a match on the class ID.
820 if (IsEqualGUID(&(curClass
->classIdentifier
), rclsid
))
823 * Since we don't do out-of process or DCOM just right away, let's ignore the
828 * We have a match, return the pointer to the class object.
830 *ppUnk
= curClass
->classObject
;
832 IUnknown_AddRef(curClass
->classObject
);
839 * Step to the next class in the list.
841 curClass
= curClass
->nextClass
;
845 LeaveCriticalSection( &csRegisteredClassList
);
847 * If we get to here, we haven't found our class.
853 _LocalServerThread(LPVOID param
) {
856 RegisteredClass
*newClass
= (RegisteredClass
*)param
;
860 unsigned char *buffer
;
862 IClassFactory
*classfac
;
863 LARGE_INTEGER seekto
;
864 ULARGE_INTEGER newpos
;
867 TRACE("Starting threader for %s.\n",debugstr_guid(&newClass
->classIdentifier
));
868 strcpy(pipefn
,PIPEPREF
);
869 WINE_StringFromCLSID(&newClass
->classIdentifier
,pipefn
+strlen(PIPEPREF
));
871 hres
= IUnknown_QueryInterface(newClass
->classObject
,&IID_IClassFactory
,(LPVOID
*)&classfac
);
872 if (hres
) return hres
;
874 hres
= CreateStreamOnHGlobal(0,TRUE
,&pStm
);
876 FIXME("Failed to create stream on hglobal.\n");
879 hres
= CoMarshalInterface(pStm
,&IID_IClassFactory
,(LPVOID
)classfac
,0,NULL
,0);
881 FIXME("CoMarshalInterface failed, %lx!\n",hres
);
884 hres
= IStream_Stat(pStm
,&ststg
,0);
885 if (hres
) return hres
;
887 buflen
= ststg
.cbSize
.s
.LowPart
;
888 buffer
= HeapAlloc(GetProcessHeap(),0,buflen
);
889 seekto
.s
.LowPart
= 0;
890 seekto
.s
.HighPart
= 0;
891 hres
= IStream_Seek(pStm
,seekto
,SEEK_SET
,&newpos
);
893 FIXME("IStream_Seek failed, %lx\n",hres
);
896 hres
= IStream_Read(pStm
,buffer
,buflen
,&res
);
898 FIXME("Stream Read failed, %lx\n",hres
);
901 IStream_Release(pStm
);
904 hPipe
= CreateNamedPipeA(
907 PIPE_TYPE_BYTE
|PIPE_WAIT
,
908 PIPE_UNLIMITED_INSTANCES
,
911 NMPWAIT_USE_DEFAULT_WAIT
,
914 if (hPipe
== INVALID_HANDLE_VALUE
) {
915 FIXME("pipe creation failed for %s, le is %lx\n",pipefn
,GetLastError());
918 if (!ConnectNamedPipe(hPipe
,NULL
)) {
919 ERR("Failure during ConnectNamedPipe %lx, ABORT!\n",GetLastError());
923 WriteFile(hPipe
,buffer
,buflen
,&res
,NULL
);
929 /******************************************************************************
930 * CoRegisterClassObject [OLE32.36]
932 * This method will register the class object for a given class ID.
934 * See the Windows documentation for more details.
936 HRESULT WINAPI
CoRegisterClassObject(
939 DWORD dwClsContext
, /* [in] CLSCTX flags indicating the context in which to run the executable */
940 DWORD flags
, /* [in] REGCLS flags indicating how connections are made */
944 RegisteredClass
* newClass
;
945 LPUNKNOWN foundObject
;
948 TRACE("(%s,%p,0x%08lx,0x%08lx,%p)\n",
949 debugstr_guid(rclsid
),pUnk
,dwClsContext
,flags
,lpdwRegister
);
951 if ( (lpdwRegister
==0) || (pUnk
==0) )
957 * First, check if the class is already registered.
958 * If it is, this should cause an error.
960 hr
= COM_GetRegisteredClassObject(rclsid
, dwClsContext
, &foundObject
);
962 IUnknown_Release(foundObject
);
963 return CO_E_OBJISREG
;
966 newClass
= HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass
));
967 if ( newClass
== NULL
)
968 return E_OUTOFMEMORY
;
970 EnterCriticalSection( &csRegisteredClassList
);
972 newClass
->classIdentifier
= *rclsid
;
973 newClass
->runContext
= dwClsContext
;
974 newClass
->connectFlags
= flags
;
976 * Use the address of the chain node as the cookie since we are sure it's
979 newClass
->dwCookie
= (DWORD
)newClass
;
980 newClass
->nextClass
= firstRegisteredClass
;
983 * Since we're making a copy of the object pointer, we have to increase its
986 newClass
->classObject
= pUnk
;
987 IUnknown_AddRef(newClass
->classObject
);
989 firstRegisteredClass
= newClass
;
990 LeaveCriticalSection( &csRegisteredClassList
);
992 *lpdwRegister
= newClass
->dwCookie
;
994 if (dwClsContext
& CLSCTX_LOCAL_SERVER
) {
998 newClass
->hThread
=CreateThread(NULL
,0,_LocalServerThread
,newClass
,0,&tid
);
1003 /***********************************************************************
1004 * CoRevokeClassObject [OLE32.40]
1006 * This method will remove a class object from the class registry
1008 * See the Windows documentation for more details.
1010 HRESULT WINAPI
CoRevokeClassObject(
1013 HRESULT hr
= E_INVALIDARG
;
1014 RegisteredClass
** prevClassLink
;
1015 RegisteredClass
* curClass
;
1017 TRACE("(%08lx)\n",dwRegister
);
1019 EnterCriticalSection( &csRegisteredClassList
);
1022 * Iterate through the whole list and try to match the cookie.
1024 curClass
= firstRegisteredClass
;
1025 prevClassLink
= &firstRegisteredClass
;
1027 while (curClass
!= 0)
1030 * Check if we have a match on the cookie.
1032 if (curClass
->dwCookie
== dwRegister
)
1035 * Remove the class from the chain.
1037 *prevClassLink
= curClass
->nextClass
;
1040 * Release the reference to the class object.
1042 IUnknown_Release(curClass
->classObject
);
1045 * Free the memory used by the chain node.
1047 HeapFree(GetProcessHeap(), 0, curClass
);
1054 * Step to the next class in the list.
1056 prevClassLink
= &(curClass
->nextClass
);
1057 curClass
= curClass
->nextClass
;
1061 LeaveCriticalSection( &csRegisteredClassList
);
1063 * If we get to here, we haven't found our class.
1068 /***********************************************************************
1069 * compobj_RegReadPath [internal]
1071 * Reads a registry value and expands it when nessesary
1073 HRESULT
compobj_RegReadPath(char * keyname
, char * valuename
, char * dst
, int dstlen
)
1079 DWORD dwLength
= dstlen
;
1081 if((hres
= RegOpenKeyExA(HKEY_CLASSES_ROOT
, keyname
, 0, KEY_READ
, &key
)) == ERROR_SUCCESS
) {
1082 if( (hres
= RegQueryValueExA(key
, NULL
, NULL
, &keytype
, (LPBYTE
)src
, &dwLength
)) == ERROR_SUCCESS
) {
1083 if (keytype
== REG_EXPAND_SZ
) {
1084 if (dstlen
<= ExpandEnvironmentStringsA(src
, dst
, dstlen
)) hres
= ERROR_MORE_DATA
;
1086 strncpy(dst
, src
, dstlen
);
1094 /***********************************************************************
1095 * CoGetClassObject [COMPOBJ.7]
1096 * CoGetClassObject [OLE32.16]
1098 * FIXME. If request allows of several options and there is a failure
1099 * with one (other than not being registered) do we try the
1100 * others or return failure? (E.g. inprocess is registered but
1101 * the DLL is not found but the server version works)
1103 HRESULT WINAPI
CoGetClassObject(
1104 REFCLSID rclsid
, DWORD dwClsContext
, COSERVERINFO
*pServerInfo
,
1105 REFIID iid
, LPVOID
*ppv
1107 LPUNKNOWN regClassObject
;
1108 HRESULT hres
= E_UNEXPECTED
;
1111 typedef HRESULT (CALLBACK
*DllGetClassObjectFunc
)(REFCLSID clsid
, REFIID iid
, LPVOID
*ppv
);
1112 DllGetClassObjectFunc DllGetClassObject
;
1114 WINE_StringFromCLSID((LPCLSID
)rclsid
,xclsid
);
1116 TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n", debugstr_guid(rclsid
), debugstr_guid(iid
));
1119 FIXME("\tpServerInfo: name=%s\n",debugstr_w(pServerInfo
->pwszName
));
1120 FIXME("\t\tpAuthInfo=%p\n",pServerInfo
->pAuthInfo
);
1124 * First, try and see if we can't match the class ID with one of the
1125 * registered classes.
1127 if (S_OK
== COM_GetRegisteredClassObject(rclsid
, dwClsContext
, ®ClassObject
))
1130 * Get the required interface from the retrieved pointer.
1132 hres
= IUnknown_QueryInterface(regClassObject
, iid
, ppv
);
1135 * Since QI got another reference on the pointer, we want to release the
1136 * one we already have. If QI was unsuccessful, this will release the object. This
1137 * is good since we are not returning it in the "out" parameter.
1139 IUnknown_Release(regClassObject
);
1144 /* first try: in-process */
1145 if ((CLSCTX_INPROC_SERVER
| CLSCTX_INPROC_HANDLER
) & dwClsContext
) {
1146 char keyname
[MAX_PATH
];
1147 char dllpath
[MAX_PATH
+1];
1149 sprintf(keyname
,"CLSID\\%s\\InprocServer32",xclsid
);
1151 if ( compobj_RegReadPath(keyname
, NULL
, dllpath
, sizeof(dllpath
)) != ERROR_SUCCESS
) {
1152 /* failure: CLSID is not found in registry */
1153 WARN("class %s not registred\n", xclsid
);
1154 hres
= REGDB_E_CLASSNOTREG
;
1156 if ((hLibrary
= LoadLibraryExA(dllpath
, 0, LOAD_WITH_ALTERED_SEARCH_PATH
)) == 0) {
1157 /* failure: DLL could not be loaded */
1158 ERR("couldn't load InprocServer32 dll %s\n", dllpath
);
1159 hres
= E_ACCESSDENIED
; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
1160 } else if (!(DllGetClassObject
= (DllGetClassObjectFunc
)GetProcAddress(hLibrary
, "DllGetClassObject"))) {
1161 /* failure: the dll did not export DllGetClassObject */
1162 ERR("couldn't find function DllGetClassObject in %s\n", dllpath
);
1163 FreeLibrary( hLibrary
);
1164 hres
= CO_E_DLLNOTFOUND
;
1166 /* OK: get the ClassObject */
1167 COMPOBJ_DLLList_Add( hLibrary
);
1168 return DllGetClassObject(rclsid
, iid
, ppv
);
1173 /* Next try out of process */
1174 if (CLSCTX_LOCAL_SERVER
& dwClsContext
)
1176 return create_marshalled_proxy(rclsid
,iid
,ppv
);
1179 /* Finally try remote */
1180 if (CLSCTX_REMOTE_SERVER
& dwClsContext
)
1182 FIXME ("CLSCTX_REMOTE_SERVER not supported\n");
1183 hres
= E_NOINTERFACE
;
1188 /***********************************************************************
1189 * CoResumeClassObjects (OLE32.173)
1191 * Resumes classobjects registered with REGCLS suspended
1193 HRESULT WINAPI
CoResumeClassObjects(void)
1199 /***********************************************************************
1200 * GetClassFile (OLE32.67)
1202 * This function supplies the CLSID associated with the given filename.
1204 HRESULT WINAPI
GetClassFile(LPCOLESTR filePathName
,CLSID
*pclsid
)
1208 int nbElm
, length
, i
;
1210 LPOLESTR
*pathDec
=0,absFile
=0,progId
=0;
1212 static const WCHAR bkslashW
[] = {'\\',0};
1213 static const WCHAR dotW
[] = {'.',0};
1215 TRACE("%s, %p\n", debugstr_w(filePathName
), pclsid
);
1217 /* if the file contain a storage object the return the CLSID writen by IStorage_SetClass method*/
1218 if((StgIsStorageFile(filePathName
))==S_OK
){
1220 res
=StgOpenStorage(filePathName
,NULL
,STGM_READ
| STGM_SHARE_DENY_WRITE
,NULL
,0,&pstg
);
1223 res
=ReadClassStg(pstg
,pclsid
);
1225 IStorage_Release(pstg
);
1229 /* if the file is not a storage object then attemps to match various bits in the file against a
1230 pattern in the registry. this case is not frequently used ! so I present only the psodocode for
1233 for(i=0;i<nFileTypes;i++)
1235 for(i=0;j<nPatternsForType;j++){
1240 pat=ReadPatternFromRegistry(i,j);
1241 hFile=CreateFileW(filePathName,,,,,,hFile);
1242 SetFilePosition(hFile,pat.offset);
1243 ReadFile(hFile,buf,pat.size,NULL,NULL);
1244 if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
1246 *pclsid=ReadCLSIDFromRegistry(i);
1252 /* if the obove strategies fail then search for the extension key in the registry */
1254 /* get the last element (absolute file) in the path name */
1255 nbElm
=FileMonikerImpl_DecomposePath(filePathName
,&pathDec
);
1256 absFile
=pathDec
[nbElm
-1];
1258 /* failed if the path represente a directory and not an absolute file name*/
1259 if (!lstrcmpW(absFile
, bkslashW
))
1260 return MK_E_INVALIDEXTENSION
;
1262 /* get the extension of the file */
1264 length
=lstrlenW(absFile
);
1265 for(i
= length
-1; (i
>= 0) && *(extension
= &absFile
[i
]) != '.'; i
--)
1268 if (!extension
|| !lstrcmpW(extension
, dotW
))
1269 return MK_E_INVALIDEXTENSION
;
1271 res
=RegQueryValueW(HKEY_CLASSES_ROOT
, extension
, NULL
, &sizeProgId
);
1273 /* get the progId associated to the extension */
1274 progId
= CoTaskMemAlloc(sizeProgId
);
1275 res
= RegQueryValueW(HKEY_CLASSES_ROOT
, extension
, progId
, &sizeProgId
);
1277 if (res
==ERROR_SUCCESS
)
1278 /* return the clsid associated to the progId */
1279 res
= CLSIDFromProgID(progId
,pclsid
);
1281 for(i
=0; pathDec
[i
]!=NULL
;i
++)
1282 CoTaskMemFree(pathDec
[i
]);
1283 CoTaskMemFree(pathDec
);
1285 CoTaskMemFree(progId
);
1287 if (res
==ERROR_SUCCESS
)
1290 return MK_E_INVALIDEXTENSION
;
1292 /***********************************************************************
1293 * CoCreateInstance [COMPOBJ.13]
1294 * CoCreateInstance [OLE32.7]
1296 HRESULT WINAPI
CoCreateInstance(
1298 LPUNKNOWN pUnkOuter
,
1304 LPCLASSFACTORY lpclf
= 0;
1313 * Initialize the "out" parameter
1318 * Get a class factory to construct the object we want.
1320 hres
= CoGetClassObject(rclsid
,
1327 FIXME("no classfactory created for CLSID %s, hres is 0x%08lx\n",
1328 debugstr_guid(rclsid
),hres
);
1333 * Create the object and don't forget to release the factory
1335 hres
= IClassFactory_CreateInstance(lpclf
, pUnkOuter
, iid
, ppv
);
1336 IClassFactory_Release(lpclf
);
1338 FIXME("no instance created for interface %s of class %s, hres is 0x%08lx\n",
1339 debugstr_guid(iid
), debugstr_guid(rclsid
),hres
);
1344 /***********************************************************************
1345 * CoCreateInstanceEx [OLE32.165]
1347 HRESULT WINAPI
CoCreateInstanceEx(
1349 LPUNKNOWN pUnkOuter
,
1351 COSERVERINFO
* pServerInfo
,
1355 IUnknown
* pUnk
= NULL
;
1358 int successCount
= 0;
1363 if ( (cmq
==0) || (pResults
==NULL
))
1364 return E_INVALIDARG
;
1366 if (pServerInfo
!=NULL
)
1367 FIXME("() non-NULL pServerInfo not supported!\n");
1370 * Initialize all the "out" parameters.
1372 for (index
= 0; index
< cmq
; index
++)
1374 pResults
[index
].pItf
= NULL
;
1375 pResults
[index
].hr
= E_NOINTERFACE
;
1379 * Get the object and get its IUnknown pointer.
1381 hr
= CoCreateInstance(rclsid
,
1391 * Then, query for all the interfaces requested.
1393 for (index
= 0; index
< cmq
; index
++)
1395 pResults
[index
].hr
= IUnknown_QueryInterface(pUnk
,
1396 pResults
[index
].pIID
,
1397 (VOID
**)&(pResults
[index
].pItf
));
1399 if (pResults
[index
].hr
== S_OK
)
1404 * Release our temporary unknown pointer.
1406 IUnknown_Release(pUnk
);
1408 if (successCount
== 0)
1409 return E_NOINTERFACE
;
1411 if (successCount
!=cmq
)
1412 return CO_S_NOTALLINTERFACES
;
1417 /***********************************************************************
1418 * CoLoadLibrary (OLE32.30)
1420 HINSTANCE WINAPI
CoLoadLibrary(LPOLESTR lpszLibName
, BOOL bAutoFree
)
1422 TRACE("(%s, %d)\n", debugstr_w(lpszLibName
), bAutoFree
);
1424 return LoadLibraryExW(lpszLibName
, 0, LOAD_WITH_ALTERED_SEARCH_PATH
);
1427 /***********************************************************************
1428 * CoFreeLibrary [OLE32.13]
1430 * NOTES: don't belive the docu
1432 void WINAPI
CoFreeLibrary(HINSTANCE hLibrary
)
1434 FreeLibrary(hLibrary
);
1438 /***********************************************************************
1439 * CoFreeAllLibraries [OLE32.12]
1441 * NOTES: don't belive the docu
1443 void WINAPI
CoFreeAllLibraries(void)
1449 /***********************************************************************
1450 * CoFreeUnusedLibraries [COMPOBJ.17]
1451 * CoFreeUnusedLibraries [OLE32.14]
1453 * FIXME: Calls to CoFreeUnusedLibraries from any thread always route
1454 * through the main apartment's thread to call DllCanUnloadNow
1456 void WINAPI
CoFreeUnusedLibraries(void)
1458 COMPOBJ_DllList_FreeUnused(0);
1461 /***********************************************************************
1462 * CoFileTimeNow [COMPOBJ.82]
1463 * CoFileTimeNow [OLE32.10]
1466 * the current system time in lpFileTime
1468 HRESULT WINAPI
CoFileTimeNow( FILETIME
*lpFileTime
) /* [out] the current time */
1470 GetSystemTimeAsFileTime( lpFileTime
);
1474 /***********************************************************************
1475 * CoLoadLibrary (OLE32.30)
1477 static void COM_RevokeAllClasses()
1479 EnterCriticalSection( &csRegisteredClassList
);
1481 while (firstRegisteredClass
!=0)
1483 CoRevokeClassObject(firstRegisteredClass
->dwCookie
);
1486 LeaveCriticalSection( &csRegisteredClassList
);
1489 /****************************************************************************
1490 * COM External Lock methods implementation
1492 * This api provides a linked list to managed external references to
1495 * The public interface consists of three calls:
1496 * COM_ExternalLockAddRef
1497 * COM_ExternalLockRelease
1498 * COM_ExternalLockFreeList
1501 #define EL_END_OF_LIST 0
1502 #define EL_NOT_FOUND 0
1505 * Declaration of the static structure that manage the
1506 * external lock to COM objects.
1508 typedef struct COM_ExternalLock COM_ExternalLock
;
1509 typedef struct COM_ExternalLockList COM_ExternalLockList
;
1511 struct COM_ExternalLock
1513 IUnknown
*pUnk
; /* IUnknown referenced */
1514 ULONG uRefCount
; /* external lock counter to IUnknown object*/
1515 COM_ExternalLock
*next
; /* Pointer to next element in list */
1518 struct COM_ExternalLockList
1520 COM_ExternalLock
*head
; /* head of list */
1524 * Declaration and initialization of the static structure that manages
1525 * the external lock to COM objects.
1527 static COM_ExternalLockList elList
= { EL_END_OF_LIST
};
1530 * Private methods used to managed the linked list
1534 static COM_ExternalLock
* COM_ExternalLockLocate(
1535 COM_ExternalLock
*element
,
1538 /****************************************************************************
1539 * Internal - Insert a new IUnknown* to the linked list
1541 static BOOL
COM_ExternalLockInsert(
1544 COM_ExternalLock
*newLock
= NULL
;
1545 COM_ExternalLock
*previousHead
= NULL
;
1548 * Allocate space for the new storage object
1550 newLock
= HeapAlloc(GetProcessHeap(), 0, sizeof(COM_ExternalLock
));
1552 if (newLock
!=NULL
) {
1553 if ( elList
.head
== EL_END_OF_LIST
) {
1554 elList
.head
= newLock
; /* The list is empty */
1556 /* insert does it at the head */
1557 previousHead
= elList
.head
;
1558 elList
.head
= newLock
;
1561 /* Set new list item data member */
1562 newLock
->pUnk
= pUnk
;
1563 newLock
->uRefCount
= 1;
1564 newLock
->next
= previousHead
;
1571 /****************************************************************************
1572 * Internal - Method that removes an item from the linked list.
1574 static void COM_ExternalLockDelete(
1575 COM_ExternalLock
*itemList
)
1577 COM_ExternalLock
*current
= elList
.head
;
1579 if ( current
== itemList
) {
1580 /* this section handles the deletion of the first node */
1581 elList
.head
= itemList
->next
;
1582 HeapFree( GetProcessHeap(), 0, itemList
);
1585 if ( current
->next
== itemList
){ /* We found the item to free */
1586 current
->next
= itemList
->next
; /* readjust the list pointers */
1587 HeapFree( GetProcessHeap(), 0, itemList
);
1591 /* Skip to the next item */
1592 current
= current
->next
;
1594 } while ( current
!= EL_END_OF_LIST
);
1598 /****************************************************************************
1599 * Internal - Recursivity agent for IUnknownExternalLockList_Find
1601 * NOTES: how long can the list be ?? (recursive!!!)
1603 static COM_ExternalLock
* COM_ExternalLockLocate( COM_ExternalLock
*element
, IUnknown
*pUnk
)
1605 if ( element
== EL_END_OF_LIST
)
1606 return EL_NOT_FOUND
;
1607 else if ( element
->pUnk
== pUnk
) /* We found it */
1609 else /* Not the right guy, keep on looking */
1610 return COM_ExternalLockLocate( element
->next
, pUnk
);
1613 /****************************************************************************
1614 * Public - Method that increments the count for a IUnknown* in the linked
1615 * list. The item is inserted if not already in the list.
1617 static void COM_ExternalLockAddRef(IUnknown
*pUnk
)
1619 COM_ExternalLock
*externalLock
= COM_ExternalLockLocate(elList
.head
, pUnk
);
1622 * Add an external lock to the object. If it was already externally
1623 * locked, just increase the reference count. If it was not.
1624 * add the item to the list.
1626 if ( externalLock
== EL_NOT_FOUND
)
1627 COM_ExternalLockInsert(pUnk
);
1629 externalLock
->uRefCount
++;
1632 * Add an internal lock to the object
1634 IUnknown_AddRef(pUnk
);
1637 /****************************************************************************
1638 * Public - Method that decrements the count for a IUnknown* in the linked
1639 * list. The item is removed from the list if its count end up at zero or if
1642 static void COM_ExternalLockRelease(
1646 COM_ExternalLock
*externalLock
= COM_ExternalLockLocate(elList
.head
, pUnk
);
1648 if ( externalLock
!= EL_NOT_FOUND
) {
1650 externalLock
->uRefCount
--; /* release external locks */
1651 IUnknown_Release(pUnk
); /* release local locks as well */
1653 if ( bRelAll
== FALSE
) break; /* perform single release */
1655 } while ( externalLock
->uRefCount
> 0 );
1657 if ( externalLock
->uRefCount
== 0 ) /* get rid of the list entry */
1658 COM_ExternalLockDelete(externalLock
);
1661 /****************************************************************************
1662 * Public - Method that frees the content of the list.
1664 static void COM_ExternalLockFreeList()
1666 COM_ExternalLock
*head
;
1668 head
= elList
.head
; /* grab it by the head */
1669 while ( head
!= EL_END_OF_LIST
) {
1670 COM_ExternalLockDelete(head
); /* get rid of the head stuff */
1671 head
= elList
.head
; /* get the new head... */
1675 /****************************************************************************
1676 * Public - Method that dump the content of the list.
1678 void COM_ExternalLockDump()
1680 COM_ExternalLock
*current
= elList
.head
;
1682 DPRINTF("\nExternal lock list contains:\n");
1684 while ( current
!= EL_END_OF_LIST
) {
1685 DPRINTF( "\t%p with %lu references count.\n", current
->pUnk
, current
->uRefCount
);
1687 /* Skip to the next item */
1688 current
= current
->next
;
1692 /******************************************************************************
1693 * CoLockObjectExternal [OLE32.31]
1695 HRESULT WINAPI
CoLockObjectExternal(
1696 LPUNKNOWN pUnk
, /* [in] object to be locked */
1697 BOOL fLock
, /* [in] do lock */
1698 BOOL fLastUnlockReleases
) /* [in] unlock all */
1703 * Increment the external lock coutner, COM_ExternalLockAddRef also
1704 * increment the object's internal lock counter.
1706 COM_ExternalLockAddRef( pUnk
);
1709 * Decrement the external lock coutner, COM_ExternalLockRelease also
1710 * decrement the object's internal lock counter.
1712 COM_ExternalLockRelease( pUnk
, fLastUnlockReleases
);
1718 /***********************************************************************
1719 * CoInitializeWOW (OLE32.27)
1721 HRESULT WINAPI
CoInitializeWOW(DWORD x
,DWORD y
) {
1722 FIXME("(0x%08lx,0x%08lx),stub!\n",x
,y
);
1726 static IUnknown
* pUnkState
= 0; /* FIXME: thread local */
1727 static int nStatCounter
= 0; /* global */
1728 static HMODULE hOleAut32
= 0; /* global */
1730 /***********************************************************************
1731 * CoGetState [OLE32.24]
1733 * NOTES: might be incomplete
1735 HRESULT WINAPI
CoGetState(IUnknown
** ppv
)
1740 IUnknown_AddRef(pUnkState
);
1742 FIXME("-- %p\n", *ppv
);
1750 /***********************************************************************
1751 * CoSetState [OLE32.42]
1753 * NOTES: FIXME: protect this with a crst
1755 HRESULT WINAPI
CoSetState(IUnknown
* pv
)
1757 FIXME("(%p),stub!\n", pv
);
1760 IUnknown_AddRef(pv
);
1762 if (nStatCounter
== 1) LoadLibraryA("OLEAUT32.DLL");
1766 TRACE("-- release %p now\n", pUnkState
);
1767 IUnknown_Release(pUnkState
);
1769 if (!nStatCounter
) FreeLibrary(hOleAut32
);
1776 /******************************************************************************
1777 * OleGetAutoConvert [OLE32.104]
1779 HRESULT WINAPI
OleGetAutoConvert(REFCLSID clsidOld
, LPCLSID pClsidNew
)
1787 sprintf(buf
,"CLSID\\");WINE_StringFromCLSID(clsidOld
,&buf
[6]);
1788 if (RegOpenKeyA(HKEY_CLASSES_ROOT
,buf
,&hkey
))
1790 res
= REGDB_E_CLASSNOTREG
;
1794 /* we can just query for the default value of AutoConvertTo key like that,
1795 without opening the AutoConvertTo key and querying for NULL (default) */
1796 if (RegQueryValueA(hkey
,"AutoConvertTo",buf
,&len
))
1798 res
= REGDB_E_KEYMISSING
;
1801 MultiByteToWideChar( CP_ACP
, 0, buf
, -1, wbuf
, sizeof(wbuf
)/sizeof(WCHAR
) );
1802 CLSIDFromString(wbuf
,pClsidNew
);
1804 if (hkey
) RegCloseKey(hkey
);
1808 /******************************************************************************
1809 * OleSetAutoConvert [OLE32.126]
1811 HRESULT WINAPI
OleSetAutoConvert(REFCLSID clsidOld
, REFCLSID clsidNew
)
1814 char buf
[200], szClsidNew
[200];
1817 TRACE("(%s,%s)\n", debugstr_guid(clsidOld
), debugstr_guid(clsidNew
));
1818 sprintf(buf
,"CLSID\\");WINE_StringFromCLSID(clsidOld
,&buf
[6]);
1819 WINE_StringFromCLSID(clsidNew
, szClsidNew
);
1820 if (RegOpenKeyA(HKEY_CLASSES_ROOT
,buf
,&hkey
))
1822 res
= REGDB_E_CLASSNOTREG
;
1825 if (RegSetValueA(hkey
, "AutoConvertTo", REG_SZ
, szClsidNew
, strlen(szClsidNew
)+1))
1827 res
= REGDB_E_WRITEREGDB
;
1832 if (hkey
) RegCloseKey(hkey
);
1836 /******************************************************************************
1837 * CoTreatAsClass [OLE32.46]
1839 HRESULT WINAPI
CoTreatAsClass(REFCLSID clsidOld
, REFCLSID clsidNew
)
1842 char buf
[200], szClsidNew
[200];
1845 FIXME("(%s,%s)\n", debugstr_guid(clsidOld
), debugstr_guid(clsidNew
));
1846 sprintf(buf
,"CLSID\\");WINE_StringFromCLSID(clsidOld
,&buf
[6]);
1847 WINE_StringFromCLSID(clsidNew
, szClsidNew
);
1848 if (RegOpenKeyA(HKEY_CLASSES_ROOT
,buf
,&hkey
))
1850 res
= REGDB_E_CLASSNOTREG
;
1853 if (RegSetValueA(hkey
, "AutoTreatAs", REG_SZ
, szClsidNew
, strlen(szClsidNew
)+1))
1855 res
= REGDB_E_WRITEREGDB
;
1860 if (hkey
) RegCloseKey(hkey
);
1865 /***********************************************************************
1866 * IsEqualGUID [OLE32.76]
1868 * Compares two Unique Identifiers.
1874 BOOL WINAPI
IsEqualGUID(
1875 REFGUID rguid1
, /* [in] unique id 1 */
1876 REFGUID rguid2
/* [in] unique id 2 */
1879 return !memcmp(rguid1
,rguid2
,sizeof(GUID
));
1882 /***********************************************************************
1883 * CoInitializeSecurity [OLE32.164]
1885 HRESULT WINAPI
CoInitializeSecurity(PSECURITY_DESCRIPTOR pSecDesc
, LONG cAuthSvc
,
1886 SOLE_AUTHENTICATION_SERVICE
* asAuthSvc
,
1887 void* pReserved1
, DWORD dwAuthnLevel
,
1888 DWORD dwImpLevel
, void* pReserved2
,
1889 DWORD dwCapabilities
, void* pReserved3
)
1891 FIXME("(%p,%ld,%p,%p,%ld,%ld,%p,%ld,%p) - stub!\n", pSecDesc
, cAuthSvc
,
1892 asAuthSvc
, pReserved1
, dwAuthnLevel
, dwImpLevel
, pReserved2
,
1893 dwCapabilities
, pReserved3
);