4 * Copyright 1995 Martin von Loewis
5 * Copyright 1998 Justin Bradford
6 * Copyright 1999 Francis Beaudet
7 * Copyright 1999 Sylvain St-Germain
26 #include "wine/unicode.h"
27 #include "wine/obj_base.h"
28 #include "wine/obj_clientserver.h"
29 #include "wine/obj_misc.h"
30 #include "wine/obj_marshal.h"
31 #include "wine/obj_storage.h"
32 #include "wine/winbase16.h"
33 #include "compobj_private.h"
36 #include "debugtools.h"
38 DEFAULT_DEBUG_CHANNEL(ole);
40 /****************************************************************************
41 * COM External Lock structures and methods declaration
43 * This api provides a linked list to managed external references to
46 * The public interface consists of three calls:
47 * COM_ExternalLockAddRef
48 * COM_ExternalLockRelease
49 * COM_ExternalLockFreeList
52 #define EL_END_OF_LIST 0
53 #define EL_NOT_FOUND 0
56 * Declaration of the static structure that manage the
57 * external lock to COM objects.
59 typedef struct COM_ExternalLock COM_ExternalLock;
60 typedef struct COM_ExternalLockList COM_ExternalLockList;
62 struct COM_ExternalLock
64 IUnknown *pUnk; /* IUnknown referenced */
65 ULONG uRefCount; /* external lock counter to IUnknown object*/
66 COM_ExternalLock *next; /* Pointer to next element in list */
69 struct COM_ExternalLockList
71 COM_ExternalLock *head; /* head of list */
75 * Declaration and initialization of the static structure that manages
76 * the external lock to COM objects.
78 static COM_ExternalLockList elList = { EL_END_OF_LIST };
81 * Public Interface to the external lock list
83 static void COM_ExternalLockFreeList();
84 static void COM_ExternalLockAddRef(IUnknown *pUnk);
85 static void COM_ExternalLockRelease(IUnknown *pUnk, BOOL bRelAll);
86 void COM_ExternalLockDump(); /* testing purposes, not static to avoid warning */
89 * Private methods used to managed the linked list
91 static BOOL COM_ExternalLockInsert(
94 static void COM_ExternalLockDelete(
95 COM_ExternalLock *element);
97 static COM_ExternalLock* COM_ExternalLockFind(
100 static COM_ExternalLock* COM_ExternalLockLocate(
101 COM_ExternalLock *element,
104 /****************************************************************************
105 * This section defines variables internal to the COM module.
107 * TODO: Most of these things will have to be made thread-safe.
109 HINSTANCE16 COMPOBJ_hInstance = 0;
110 HINSTANCE COMPOBJ_hInstance32 = 0;
111 static int COMPOBJ_Attach = 0;
113 LPMALLOC16 currentMalloc16=NULL;
114 LPMALLOC currentMalloc32=NULL;
117 WORD Table_ETask[62];
120 * This lock count counts the number of times CoInitialize is called. It is
121 * decreased every time CoUninitialize is called. When it hits 0, the COM
122 * libraries are freed
124 static LONG s_COMLockCount = 0;
127 * This linked list contains the list of registered class objects. These
128 * are mostly used to register the factories for out-of-proc servers of OLE
131 * TODO: Make this data structure aware of inter-process communication. This
132 * means that parts of this will be exported to the Wine Server.
134 typedef struct tagRegisteredClass
136 CLSID classIdentifier;
137 LPUNKNOWN classObject;
141 struct tagRegisteredClass* nextClass;
144 static CRITICAL_SECTION csRegisteredClassList;
145 static RegisteredClass* firstRegisteredClass = NULL;
147 /* this open DLL table belongs in a per process table, but my guess is that
148 * it shouldn't live in the kernel, so I'll put them out here in DLL
149 * space assuming that there is one OLE32 per process.
151 typedef struct tagOpenDll {
153 struct tagOpenDll *next;
156 static CRITICAL_SECTION csOpenDllList;
157 static OpenDll *openDllList = NULL; /* linked list of open dlls */
159 /*****************************************************************************
160 * This section contains prototypes to internal methods for this
163 static HRESULT COM_GetRegisteredClassObject(REFCLSID rclsid,
167 static void COM_RevokeAllClasses();
170 /******************************************************************************
171 * Initialize/Uninitialize critical sections.
173 void COMPOBJ_InitProcess( void )
175 InitializeCriticalSection( &csRegisteredClassList );
176 InitializeCriticalSection( &csOpenDllList );
179 void COMPOBJ_UninitProcess( void )
181 DeleteCriticalSection( &csRegisteredClassList );
182 DeleteCriticalSection( &csOpenDllList );
185 /******************************************************************************
186 * CoBuildVersion [COMPOBJ.1]
187 * CoBuildVersion [OLE32.4]
190 * Current build version, hiword is majornumber, loword is minornumber
192 DWORD WINAPI CoBuildVersion(void)
194 TRACE("Returning version %d, build %d.\n", rmm, rup);
195 return (rmm<<16)+rup;
198 /******************************************************************************
199 * CoInitialize [COMPOBJ.2]
200 * Set the win16 IMalloc used for memory management
202 HRESULT WINAPI CoInitialize16(
203 LPVOID lpReserved /* [in] pointer to win16 malloc interface */
205 currentMalloc16 = (LPMALLOC16)lpReserved;
209 /******************************************************************************
210 * CoInitialize [OLE32.26]
212 * Initializes the COM libraries.
216 HRESULT WINAPI CoInitialize(
217 LPVOID lpReserved /* [in] pointer to win32 malloc interface
218 (obsolete, should be NULL) */
222 * Just delegate to the newer method.
224 return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
227 /******************************************************************************
228 * CoInitializeEx [OLE32.163]
230 * Initializes the COM libraries. The behavior used to set the win32 IMalloc
231 * used for memory management is obsolete.
234 * S_OK if successful,
235 * S_FALSE if this function was called already.
236 * RPC_E_CHANGED_MODE if a previous call to CoInitialize specified another
240 * Only the single threaded model is supported. As a result RPC_E_CHANGED_MODE
243 * See the windows documentation for more details.
245 HRESULT WINAPI CoInitializeEx(
246 LPVOID lpReserved, /* [in] pointer to win32 malloc interface
247 (obsolete, should be NULL) */
248 DWORD dwCoInit /* [in] A value from COINIT specifies the threading model */
253 TRACE("(%p, %x)\n", lpReserved, (int)dwCoInit);
255 if (lpReserved!=NULL)
257 ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved);
261 * Check for unsupported features.
263 if (dwCoInit!=COINIT_APARTMENTTHREADED)
265 FIXME(":(%p,%x): unsupported flag %x\n", lpReserved, (int)dwCoInit, (int)dwCoInit);
266 /* Hope for the best and continue anyway */
270 * Check the lock count. If this is the first time going through the initialize
271 * process, we have to initialize the libraries.
273 * And crank-up that lock count.
275 if (InterlockedExchangeAdd(&s_COMLockCount,1)==0)
278 * Initialize the various COM libraries and data structures.
280 TRACE("() - Initializing the COM libraries\n");
283 RunningObjectTableImpl_Initialize();
293 /***********************************************************************
294 * CoUninitialize [COMPOBJ.3]
295 * Don't know what it does.
296 * 3-Nov-98 -- this was originally misspelled, I changed it to what I
297 * believe is the correct spelling
299 void WINAPI CoUninitialize16(void)
302 CoFreeAllLibraries();
305 /***********************************************************************
306 * CoUninitialize [OLE32.47]
308 * This method will release the COM libraries.
310 * See the windows documentation for more details.
312 void WINAPI CoUninitialize(void)
318 * Decrease the reference count.
319 * If we are back to 0 locks on the COM library, make sure we free
320 * all the associated data structures.
322 lCOMRefCnt = InterlockedExchangeAdd(&s_COMLockCount,-1);
326 * Release the various COM libraries and data structures.
328 TRACE("() - Releasing the COM libraries\n");
330 RunningObjectTableImpl_UnInitialize();
332 * Release the references to the registered class objects.
334 COM_RevokeAllClasses();
337 * This will free the loaded COM Dlls.
339 CoFreeAllLibraries();
342 * This will free list of external references to COM objects.
344 COM_ExternalLockFreeList();
347 else if (lCOMRefCnt<1) {
348 ERR( "CoUninitialize() - not CoInitialized.\n" );
349 InterlockedExchangeAdd(&s_COMLockCount,1); /* restore the lock count. */
353 /***********************************************************************
354 * CoGetMalloc [COMPOBJ.4]
356 * The current win16 IMalloc
358 HRESULT WINAPI CoGetMalloc16(
359 DWORD dwMemContext, /* [in] unknown */
360 LPMALLOC16 * lpMalloc /* [out] current win16 malloc interface */
363 currentMalloc16 = IMalloc16_Constructor();
364 *lpMalloc = currentMalloc16;
368 /******************************************************************************
369 * CoGetMalloc [OLE32.20]
372 * The current win32 IMalloc
374 HRESULT WINAPI CoGetMalloc(
375 DWORD dwMemContext, /* [in] unknown */
376 LPMALLOC *lpMalloc /* [out] current win32 malloc interface */
379 currentMalloc32 = IMalloc_Constructor();
380 *lpMalloc = currentMalloc32;
384 /***********************************************************************
385 * CoCreateStandardMalloc [COMPOBJ.71]
387 HRESULT WINAPI CoCreateStandardMalloc16(DWORD dwMemContext,
388 LPMALLOC16 *lpMalloc)
390 /* FIXME: docu says we shouldn't return the same allocator as in
392 *lpMalloc = IMalloc16_Constructor();
396 /******************************************************************************
397 * CoDisconnectObject [COMPOBJ.15]
398 * CoDisconnectObject [OLE32.8]
400 HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
402 TRACE("(%p, %lx)\n",lpUnk,reserved);
406 /***********************************************************************
407 * IsEqualGUID [COMPOBJ.18]
409 * Compares two Unique Identifiers.
414 BOOL16 WINAPI IsEqualGUID16(
415 GUID* g1, /* [in] unique id 1 */
416 GUID* g2 /* [in] unique id 2 */
418 return !memcmp( g1, g2, sizeof(GUID) );
421 /******************************************************************************
422 * CLSIDFromString [COMPOBJ.20]
423 * Converts a unique identifier from its string representation into
426 * Class id: DWORD-WORD-WORD-BYTES[2]-BYTES[6]
431 HRESULT WINAPI CLSIDFromString16(
432 LPCOLESTR16 idstr, /* [in] string representation of guid */
433 CLSID *id /* [out] GUID converted from string */
435 BYTE *s = (BYTE *) idstr;
441 s = "{00000000-0000-0000-0000-000000000000}";
442 else { /* validate the CLSID string */
445 return CO_E_CLASSSTRING;
447 if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') || (s[24]!='-') || (s[37]!='}'))
448 return CO_E_CLASSSTRING;
452 if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue;
453 if (!(((s[i] >= '0') && (s[i] <= '9')) ||
454 ((s[i] >= 'a') && (s[i] <= 'f')) ||
455 ((s[i] >= 'A') && (s[i] <= 'F')))
457 return CO_E_CLASSSTRING;
461 TRACE("%s -> %p\n", s, id);
463 /* quick lookup table */
464 memset(table, 0, 256);
466 for (i = 0; i < 10; i++) {
469 for (i = 0; i < 6; i++) {
470 table['A' + i] = i+10;
471 table['a' + i] = i+10;
474 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
478 s++; /* skip leading brace */
479 for (i = 0; i < 4; i++) {
480 p[3 - i] = table[*s]<<4 | table[*(s+1)];
486 for (i = 0; i < 2; i++) {
487 p[1-i] = table[*s]<<4 | table[*(s+1)];
493 for (i = 0; i < 2; i++) {
494 p[1-i] = table[*s]<<4 | table[*(s+1)];
500 /* these are just sequential bytes */
501 for (i = 0; i < 2; i++) {
502 *p++ = table[*s]<<4 | table[*(s+1)];
507 for (i = 0; i < 6; i++) {
508 *p++ = table[*s]<<4 | table[*(s+1)];
515 /******************************************************************************
516 * CoCreateGuid[OLE32.6]
519 HRESULT WINAPI CoCreateGuid(
520 GUID *pguid /* [out] points to the GUID to initialize */
522 return UuidCreate(pguid);
525 /******************************************************************************
526 * CLSIDFromString [OLE32.3]
527 * IIDFromString [OLE32.74]
528 * Converts a unique identifier from its string representation into
532 * If idstr is not a valid CLSID string then it gets treated as a ProgID
537 HRESULT WINAPI CLSIDFromString(
538 LPCOLESTR idstr, /* [in] string representation of GUID */
539 CLSID *id ) /* [out] GUID represented by above string */
544 if (!WideCharToMultiByte( CP_ACP, 0, idstr, -1, xid, sizeof(xid), NULL, NULL ))
545 return CO_E_CLASSSTRING;
546 ret = CLSIDFromString16(xid,id);
547 if(ret != S_OK) { /* It appears a ProgID is also valid */
548 ret = CLSIDFromProgID(idstr, id);
553 /******************************************************************************
554 * WINE_StringFromCLSID [Internal]
555 * Converts a GUID into the respective string representation.
560 * the string representation and HRESULT
562 static HRESULT WINE_StringFromCLSID(
563 const CLSID *id, /* [in] GUID to be converted */
564 LPSTR idstr /* [out] pointer to buffer to contain converted guid */
566 static const char *hex = "0123456789ABCDEF";
571 { ERR("called with id=Null\n");
576 sprintf(idstr, "{%08lX-%04X-%04X-%02X%02X-",
577 id->Data1, id->Data2, id->Data3,
578 id->Data4[0], id->Data4[1]);
582 for (i = 2; i < 8; i++) {
583 *s++ = hex[id->Data4[i]>>4];
584 *s++ = hex[id->Data4[i] & 0xf];
590 TRACE("%p->%s\n", id, idstr);
595 /******************************************************************************
596 * StringFromCLSID [COMPOBJ.19]
597 * Converts a GUID into the respective string representation.
598 * The target string is allocated using the OLE IMalloc.
600 * the string representation and HRESULT
602 HRESULT WINAPI StringFromCLSID16(
603 REFCLSID id, /* [in] the GUID to be converted */
604 LPOLESTR16 *idstr /* [out] a pointer to a to-be-allocated segmented pointer pointing to the resulting string */
607 extern BOOL WINAPI K32WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags,
608 DWORD cbArgs, LPVOID pArgs, LPDWORD pdwRetCode );
613 ret = CoGetMalloc16(0,&mllc);
616 args[0] = (DWORD)mllc;
619 /* No need for a Callback entry, we have WOWCallback16Ex which does
620 * everything we need.
622 if (!K32WOWCallback16Ex(
623 (DWORD)((ICOM_VTABLE(IMalloc16)*)MapSL(
624 (SEGPTR)ICOM_VTBL(((LPMALLOC16)MapSL((SEGPTR)mllc))))
631 WARN("CallTo16 IMalloc16 failed\n");
634 return WINE_StringFromCLSID(id,MapSL((SEGPTR)*idstr));
637 /******************************************************************************
638 * StringFromCLSID [OLE32.151]
639 * StringFromIID [OLE32.153]
640 * Converts a GUID into the respective string representation.
641 * The target string is allocated using the OLE IMalloc.
643 * the string representation and HRESULT
645 HRESULT WINAPI StringFromCLSID(
646 REFCLSID id, /* [in] the GUID to be converted */
647 LPOLESTR *idstr /* [out] a pointer to a to-be-allocated pointer pointing to the resulting string */
653 if ((ret=CoGetMalloc(0,&mllc)))
656 ret=WINE_StringFromCLSID(id,buf);
658 DWORD len = MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 );
659 *idstr = IMalloc_Alloc( mllc, len * sizeof(WCHAR) );
660 MultiByteToWideChar( CP_ACP, 0, buf, -1, *idstr, len );
665 /******************************************************************************
666 * StringFromGUID2 [COMPOBJ.76]
667 * StringFromGUID2 [OLE32.152]
669 * Converts a global unique identifier into a string of an API-
670 * specified fixed format. (The usual {.....} stuff.)
673 * The (UNICODE) string representation of the GUID in 'str'
674 * The length of the resulting string, 0 if there was any problem.
677 StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
681 if (WINE_StringFromCLSID(id,xguid))
683 return MultiByteToWideChar( CP_ACP, 0, xguid, -1, str, cmax );
686 /******************************************************************************
687 * ProgIDFromCLSID [OLE32.133]
688 * Converts a class id into the respective Program ID. (By using a registry lookup)
689 * RETURNS S_OK on success
690 * riid associated with the progid
693 HRESULT WINAPI ProgIDFromCLSID(
694 REFCLSID clsid, /* [in] class id as found in registry */
695 LPOLESTR *lplpszProgID/* [out] associated Prog ID */
698 char strCLSID[50], *buf, *buf2;
704 WINE_StringFromCLSID(clsid, strCLSID);
706 buf = HeapAlloc(GetProcessHeap(), 0, strlen(strCLSID)+14);
707 sprintf(buf,"CLSID\\%s\\ProgID", strCLSID);
708 if (RegOpenKeyA(HKEY_CLASSES_ROOT, buf, &xhkey))
709 ret = REGDB_E_CLASSNOTREG;
711 HeapFree(GetProcessHeap(), 0, buf);
715 buf2 = HeapAlloc(GetProcessHeap(), 0, 255);
717 if (RegQueryValueA(xhkey, NULL, buf2, &buf2len))
718 ret = REGDB_E_CLASSNOTREG;
722 if (CoGetMalloc(0,&mllc))
726 DWORD len = MultiByteToWideChar( CP_ACP, 0, buf2, -1, NULL, 0 );
727 *lplpszProgID = IMalloc_Alloc(mllc, len * sizeof(WCHAR) );
728 MultiByteToWideChar( CP_ACP, 0, buf2, -1, *lplpszProgID, len );
731 HeapFree(GetProcessHeap(), 0, buf2);
738 /******************************************************************************
739 * CLSIDFromProgID [COMPOBJ.61]
740 * Converts a program id into the respective GUID. (By using a registry lookup)
742 * riid associated with the progid
744 HRESULT WINAPI CLSIDFromProgID16(
745 LPCOLESTR16 progid, /* [in] program id as found in registry */
746 LPCLSID riid /* [out] associated CLSID */
753 buf = HeapAlloc(GetProcessHeap(),0,strlen(progid)+8);
754 sprintf(buf,"%s\\CLSID",progid);
755 if ((err=RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&xhkey))) {
756 HeapFree(GetProcessHeap(),0,buf);
757 return CO_E_CLASSSTRING;
759 HeapFree(GetProcessHeap(),0,buf);
760 buf2len = sizeof(buf2);
761 if ((err=RegQueryValueA(xhkey,NULL,buf2,&buf2len))) {
763 return CO_E_CLASSSTRING;
766 return CLSIDFromString16(buf2,riid);
769 /******************************************************************************
770 * CLSIDFromProgID [OLE32.2]
771 * Converts a program id into the respective GUID. (By using a registry lookup)
773 * riid associated with the progid
775 HRESULT WINAPI CLSIDFromProgID(
776 LPCOLESTR progid, /* [in] program id as found in registry */
777 LPCLSID riid ) /* [out] associated CLSID */
779 static const WCHAR clsidW[] = { '\\','C','L','S','I','D',0 };
781 DWORD buf2len = sizeof(buf2);
784 WCHAR *buf = HeapAlloc( GetProcessHeap(),0,(strlenW(progid)+8) * sizeof(WCHAR) );
785 strcpyW( buf, progid );
786 strcatW( buf, clsidW );
787 if (RegOpenKeyW(HKEY_CLASSES_ROOT,buf,&xhkey))
789 HeapFree(GetProcessHeap(),0,buf);
790 return CO_E_CLASSSTRING;
792 HeapFree(GetProcessHeap(),0,buf);
794 if (RegQueryValueA(xhkey,NULL,buf2,&buf2len))
797 return CO_E_CLASSSTRING;
800 return CLSIDFromString16(buf2,riid);
805 /*****************************************************************************
806 * CoGetPSClsid [OLE32.22]
808 * This function returns the CLSID of the DLL that implements the proxy and stub
809 * for the specified interface.
811 * It determines this by searching the
812 * HKEY_CLASSES_ROOT\Interface\{string form of riid}\ProxyStubClsid32 in the registry
813 * and any interface id registered by CoRegisterPSClsid within the current process.
815 * FIXME: We only search the registry, not ids registered with CoRegisterPSClsid.
817 HRESULT WINAPI CoGetPSClsid(
818 REFIID riid, /* [in] Interface whose proxy/stub CLSID is to be returned */
819 CLSID *pclsid ) /* [out] Where to store returned proxy/stub CLSID */
825 TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid), pclsid);
827 /* Get the input iid as a string */
828 WINE_StringFromCLSID(riid, buf2);
829 /* Allocate memory for the registry key we will construct.
830 (length of iid string plus constant length of static text */
831 buf = HeapAlloc(GetProcessHeap(), 0, strlen(buf2)+27);
834 return (E_OUTOFMEMORY);
837 /* Construct the registry key we want */
838 sprintf(buf,"Interface\\%s\\ProxyStubClsid32", buf2);
841 if (RegOpenKeyA(HKEY_CLASSES_ROOT, buf, &xhkey))
843 HeapFree(GetProcessHeap(),0,buf);
844 return (E_INVALIDARG);
846 HeapFree(GetProcessHeap(),0,buf);
848 /* ... Once we have the key, query the registry to get the
849 value of CLSID as a string, and convert it into a
850 proper CLSID structure to be passed back to the app */
851 buf2len = sizeof(buf2);
852 if ( (RegQueryValueA(xhkey,NULL,buf2,&buf2len)) )
859 /* We have the CLSid we want back from the registry as a string, so
860 lets convert it into a CLSID structure */
861 if ( (CLSIDFromString16(buf2,pclsid)) != NOERROR)
866 TRACE ("() Returning CLSID=%s\n", debugstr_guid(pclsid));
872 /***********************************************************************
873 * WriteClassStm (OLE32.159)
875 * This function write a CLSID on stream
877 HRESULT WINAPI WriteClassStm(IStream *pStm,REFCLSID rclsid)
879 TRACE("(%p,%p)\n",pStm,rclsid);
884 return IStream_Write(pStm,rclsid,sizeof(CLSID),NULL);
887 /***********************************************************************
888 * ReadClassStm (OLE32.135)
890 * This function read a CLSID from a stream
892 HRESULT WINAPI ReadClassStm(IStream *pStm,CLSID *pclsid)
897 TRACE("(%p,%p)\n",pStm,pclsid);
902 res = IStream_Read(pStm,(void*)pclsid,sizeof(CLSID),&nbByte);
907 if (nbByte != sizeof(CLSID))
913 /* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
914 /***********************************************************************
915 * LookupETask (COMPOBJ.94)
917 HRESULT WINAPI LookupETask16(HTASK16 *hTask,LPVOID p) {
918 FIXME("(%p,%p),stub!\n",hTask,p);
919 if ((*hTask = GetCurrentTask()) == hETask) {
920 memcpy(p, Table_ETask, sizeof(Table_ETask));
925 /* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
926 /***********************************************************************
927 * SetETask (COMPOBJ.95)
929 HRESULT WINAPI SetETask16(HTASK16 hTask, LPVOID p) {
930 FIXME("(%04x,%p),stub!\n",hTask,p);
935 /* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
936 /***********************************************************************
937 * CALLOBJECTINWOW (COMPOBJ.201)
939 HRESULT WINAPI CallObjectInWOW(LPVOID p1,LPVOID p2) {
940 FIXME("(%p,%p),stub!\n",p1,p2);
944 /******************************************************************************
945 * CoRegisterClassObject [COMPOBJ.5]
947 * Don't know where it registers it ...
949 HRESULT WINAPI CoRegisterClassObject16(
952 DWORD dwClsContext, /* [in] CLSCTX flags indicating the context in which to run the executable */
953 DWORD flags, /* [in] REGCLS flags indicating how connections are made */
958 WINE_StringFromCLSID(rclsid,buf);
960 FIXME("(%s,%p,0x%08lx,0x%08lx,%p),stub\n",
961 buf,pUnk,dwClsContext,flags,lpdwRegister
967 /******************************************************************************
968 * CoRevokeClassObject [COMPOBJ.6]
971 HRESULT WINAPI CoRevokeClassObject16(DWORD dwRegister) /* [in] token on class obj */
973 FIXME("(0x%08lx),stub!\n", dwRegister);
977 /******************************************************************************
978 * CoFileTimeToDosDateTime [COMPOBJ.30]
980 BOOL16 WINAPI CoFileTimeToDosDateTime16(const FILETIME *ft, LPWORD lpDosDate, LPWORD lpDosTime)
982 return FileTimeToDosDateTime(ft, lpDosDate, lpDosTime);
985 /******************************************************************************
986 * CoDosDateTimeToFileTime [COMPOBJ.31]
988 BOOL16 WINAPI CoDosDateTimeToFileTime16(WORD wDosDate, WORD wDosTime, FILETIME *ft)
990 return DosDateTimeToFileTime(wDosDate, wDosTime, ft);
994 * COM_GetRegisteredClassObject
996 * This internal method is used to scan the registered class list to
997 * find a class object.
1000 * rclsid Class ID of the class to find.
1001 * dwClsContext Class context to match.
1002 * ppv [out] returns a pointer to the class object. Complying
1003 * to normal COM usage, this method will increase the
1004 * reference count on this object.
1006 static HRESULT COM_GetRegisteredClassObject(
1011 HRESULT hr = S_FALSE;
1012 RegisteredClass* curClass;
1014 EnterCriticalSection( &csRegisteredClassList );
1022 * Iterate through the whole list and try to match the class ID.
1024 curClass = firstRegisteredClass;
1026 while (curClass != 0)
1029 * Check if we have a match on the class ID.
1031 if (IsEqualGUID(&(curClass->classIdentifier), rclsid))
1034 * Since we don't do out-of process or DCOM just right away, let's ignore the
1039 * We have a match, return the pointer to the class object.
1041 *ppUnk = curClass->classObject;
1043 IUnknown_AddRef(curClass->classObject);
1050 * Step to the next class in the list.
1052 curClass = curClass->nextClass;
1056 LeaveCriticalSection( &csRegisteredClassList );
1058 * If we get to here, we haven't found our class.
1063 /******************************************************************************
1064 * CoRegisterClassObject [OLE32.36]
1066 * This method will register the class object for a given class ID.
1068 * See the Windows documentation for more details.
1070 HRESULT WINAPI CoRegisterClassObject(
1073 DWORD dwClsContext, /* [in] CLSCTX flags indicating the context in which to run the executable */
1074 DWORD flags, /* [in] REGCLS flags indicating how connections are made */
1075 LPDWORD lpdwRegister
1078 RegisteredClass* newClass;
1079 LPUNKNOWN foundObject;
1083 WINE_StringFromCLSID(rclsid,buf);
1085 TRACE("(%s,%p,0x%08lx,0x%08lx,%p)\n",
1086 buf,pUnk,dwClsContext,flags,lpdwRegister);
1089 * Perform a sanity check on the parameters
1091 if ( (lpdwRegister==0) || (pUnk==0) )
1093 return E_INVALIDARG;
1097 * Initialize the cookie (out parameter)
1102 * First, check if the class is already registered.
1103 * If it is, this should cause an error.
1105 hr = COM_GetRegisteredClassObject(rclsid, dwClsContext, &foundObject);
1110 * The COM_GetRegisteredClassObject increased the reference count on the
1111 * object so it has to be released.
1113 IUnknown_Release(foundObject);
1115 return CO_E_OBJISREG;
1119 * If it is not registered, we must create a new entry for this class and
1120 * append it to the registered class list.
1121 * We use the address of the chain node as the cookie since we are sure it's
1124 newClass = HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass));
1125 if ( newClass == NULL )
1126 return E_OUTOFMEMORY;
1128 EnterCriticalSection( &csRegisteredClassList );
1130 * Initialize the node.
1132 newClass->classIdentifier = *rclsid;
1133 newClass->runContext = dwClsContext;
1134 newClass->connectFlags = flags;
1135 newClass->dwCookie = (DWORD)newClass;
1136 newClass->nextClass = firstRegisteredClass;
1139 * Since we're making a copy of the object pointer, we have to increase its
1142 newClass->classObject = pUnk;
1143 IUnknown_AddRef(newClass->classObject);
1145 firstRegisteredClass = newClass;
1147 LeaveCriticalSection( &csRegisteredClassList );
1150 * Assign the out parameter (cookie)
1152 *lpdwRegister = newClass->dwCookie;
1155 * We're successful Yippee!
1160 /***********************************************************************
1161 * CoRevokeClassObject [OLE32.40]
1163 * This method will remove a class object from the class registry
1165 * See the Windows documentation for more details.
1167 HRESULT WINAPI CoRevokeClassObject(
1170 HRESULT hr = E_INVALIDARG;
1171 RegisteredClass** prevClassLink;
1172 RegisteredClass* curClass;
1174 TRACE("(%08lx)\n",dwRegister);
1176 EnterCriticalSection( &csRegisteredClassList );
1179 * Iterate through the whole list and try to match the cookie.
1181 curClass = firstRegisteredClass;
1182 prevClassLink = &firstRegisteredClass;
1184 while (curClass != 0)
1187 * Check if we have a match on the cookie.
1189 if (curClass->dwCookie == dwRegister)
1192 * Remove the class from the chain.
1194 *prevClassLink = curClass->nextClass;
1197 * Release the reference to the class object.
1199 IUnknown_Release(curClass->classObject);
1202 * Free the memory used by the chain node.
1204 HeapFree(GetProcessHeap(), 0, curClass);
1211 * Step to the next class in the list.
1213 prevClassLink = &(curClass->nextClass);
1214 curClass = curClass->nextClass;
1218 LeaveCriticalSection( &csRegisteredClassList );
1220 * If we get to here, we haven't found our class.
1225 /***********************************************************************
1226 * CoGetClassObject [COMPOBJ.7]
1227 * CoGetClassObject [OLE32.16]
1229 * FIXME. If request allows of several options and there is a failure
1230 * with one (other than not being registered) do we try the
1231 * others or return failure? (E.g. inprocess is registered but
1232 * the DLL is not found but the server version works)
1234 HRESULT WINAPI CoGetClassObject(
1235 REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo,
1236 REFIID iid, LPVOID *ppv
1238 LPUNKNOWN regClassObject;
1239 HRESULT hres = E_UNEXPECTED;
1241 WCHAR ProviderName[MAX_PATH+1];
1242 DWORD ProviderNameLen = sizeof(ProviderName);
1244 typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid,
1245 REFIID iid, LPVOID *ppv);
1246 DllGetClassObjectFunc DllGetClassObject;
1250 WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
1252 TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",
1253 debugstr_guid(rclsid),
1258 FIXME("\tpServerInfo: name=%s\n",debugstr_w(pServerInfo->pwszName));
1259 FIXME("\t\tpAuthInfo=%p\n",pServerInfo->pAuthInfo);
1263 * First, try and see if we can't match the class ID with one of the
1264 * registered classes.
1266 if (S_OK == COM_GetRegisteredClassObject(rclsid, dwClsContext, ®ClassObject))
1269 * Get the required interface from the retrieved pointer.
1271 hres = IUnknown_QueryInterface(regClassObject, iid, ppv);
1274 * Since QI got another reference on the pointer, we want to release the
1275 * one we already have. If QI was unsuccessful, this will release the object. This
1276 * is good since we are not returning it in the "out" parameter.
1278 IUnknown_Release(regClassObject);
1283 /* Then try for in-process */
1284 if ((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext)
1286 memset(ProviderName,0,sizeof(ProviderName));
1287 sprintf(buf,"CLSID\\%s\\InprocServer32",xclsid);
1288 if (((hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key)) != ERROR_SUCCESS) ||
1289 ((hres = RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)ProviderName,&ProviderNameLen)),
1291 hres != ERROR_SUCCESS))
1293 hres = REGDB_E_CLASSNOTREG;
1295 /* Don't ask me. MSDN says that CoGetClassObject does NOT call CoLoadLibrary */
1296 else if ((hLibrary = CoLoadLibrary(ProviderName, TRUE)) == 0)
1298 FIXME("couldn't load InprocServer32 dll %s\n", debugstr_w(ProviderName));
1299 hres = E_ACCESSDENIED; /* or should this be CO_E_DLLNOTFOUND? */
1301 else if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject")))
1303 /* not sure if this should be called here CoFreeLibrary(hLibrary);*/
1304 FIXME("couldn't find function DllGetClassObject in %s\n", debugstr_w(ProviderName));
1305 hres = E_ACCESSDENIED;
1309 /* Ask the DLL for its class object. (there was a note here about
1310 * class factories but this is good.
1312 return DllGetClassObject(rclsid, iid, ppv);
1317 /* Finally try out of process */
1318 /* out of process and remote servers not supported yet */
1319 if (CLSCTX_LOCAL_SERVER & dwClsContext)
1321 memset(ProviderName,0,sizeof(ProviderName));
1322 sprintf(buf,"CLSID\\%s\\LocalServer32",xclsid);
1323 if (((hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key)) != ERROR_SUCCESS) ||
1324 ((hres = RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)ProviderName,&ProviderNameLen)),
1326 hres != ERROR_SUCCESS))
1328 hres = REGDB_E_CLASSNOTREG;
1332 /* CO_E_APPNOTFOUND if no exe */
1333 FIXME("CLSCTX_LOCAL_SERVER %s registered but not yet supported!\n",debugstr_w(ProviderName));
1334 hres = E_ACCESSDENIED;
1338 if (CLSCTX_REMOTE_SERVER & dwClsContext)
1340 FIXME ("CLSCTX_REMOTE_SERVER not supported\n");
1341 hres = E_ACCESSDENIED;
1346 /***********************************************************************
1347 * CoResumeClassObjects (OLE32.173)
1349 * Resumes classobjects registered with REGCLS suspended
1351 HRESULT WINAPI CoResumeClassObjects(void)
1357 /***********************************************************************
1358 * GetClassFile (OLE32.67)
1360 * This function supplies the CLSID associated with the given filename.
1362 HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
1366 int nbElm=0,length=0,i=0;
1368 LPOLESTR *pathDec=0,absFile=0,progId=0;
1369 WCHAR extention[100]={0};
1373 /* if the file contain a storage object the return the CLSID writen by IStorage_SetClass method*/
1374 if((StgIsStorageFile(filePathName))==S_OK){
1376 res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
1379 res=ReadClassStg(pstg,pclsid);
1381 IStorage_Release(pstg);
1385 /* if the file is not a storage object then attemps to match various bits in the file against a
1386 pattern in the registry. this case is not frequently used ! so I present only the psodocode for
1389 for(i=0;i<nFileTypes;i++)
1391 for(i=0;j<nPatternsForType;j++){
1396 pat=ReadPatternFromRegistry(i,j);
1397 hFile=CreateFileW(filePathName,,,,,,hFile);
1398 SetFilePosition(hFile,pat.offset);
1399 ReadFile(hFile,buf,pat.size,NULL,NULL);
1400 if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
1402 *pclsid=ReadCLSIDFromRegistry(i);
1408 /* if the obove strategies fail then search for the extension key in the registry */
1410 /* get the last element (absolute file) in the path name */
1411 nbElm=FileMonikerImpl_DecomposePath(filePathName,&pathDec);
1412 absFile=pathDec[nbElm-1];
1414 /* failed if the path represente a directory and not an absolute file name*/
1415 if (lstrcmpW(absFile,(LPOLESTR)"\\"))
1416 return MK_E_INVALIDEXTENSION;
1418 /* get the extension of the file */
1419 length=lstrlenW(absFile);
1420 for(i=length-1; ( (i>=0) && (extention[i]=absFile[i]) );i--);
1422 /* get the progId associated to the extension */
1423 progId=CoTaskMemAlloc(sizeProgId);
1425 res=RegQueryValueW(HKEY_CLASSES_ROOT,extention,progId,&sizeProgId);
1427 if (res==ERROR_MORE_DATA){
1429 progId = CoTaskMemRealloc(progId,sizeProgId);
1430 res=RegQueryValueW(HKEY_CLASSES_ROOT,extention,progId,&sizeProgId);
1432 if (res==ERROR_SUCCESS)
1433 /* return the clsid associated to the progId */
1434 res= CLSIDFromProgID(progId,pclsid);
1436 for(i=0; pathDec[i]!=NULL;i++)
1437 CoTaskMemFree(pathDec[i]);
1438 CoTaskMemFree(pathDec);
1440 CoTaskMemFree(progId);
1442 if (res==ERROR_SUCCESS)
1445 return MK_E_INVALIDEXTENSION;
1447 /******************************************************************************
1448 * CoRegisterMessageFilter [COMPOBJ.27]
1450 HRESULT WINAPI CoRegisterMessageFilter16(
1451 LPMESSAGEFILTER lpMessageFilter,
1452 LPMESSAGEFILTER *lplpMessageFilter
1454 FIXME("(%p,%p),stub!\n",lpMessageFilter,lplpMessageFilter);
1458 /***********************************************************************
1459 * CoCreateInstance [COMPOBJ.13]
1460 * CoCreateInstance [OLE32.7]
1462 HRESULT WINAPI CoCreateInstance(
1464 LPUNKNOWN pUnkOuter,
1470 LPCLASSFACTORY lpclf = 0;
1479 * Initialize the "out" parameter
1484 * Get a class factory to construct the object we want.
1486 hres = CoGetClassObject(rclsid,
1493 FIXME("no classfactory created for CLSID %s, hres is 0x%08lx\n",
1494 debugstr_guid(rclsid),hres);
1499 * Create the object and don't forget to release the factory
1501 hres = IClassFactory_CreateInstance(lpclf, pUnkOuter, iid, ppv);
1502 IClassFactory_Release(lpclf);
1504 FIXME("no instance created for interface %s of class %s, hres is 0x%08lx\n",
1505 debugstr_guid(iid), debugstr_guid(rclsid),hres);
1510 /***********************************************************************
1511 * CoCreateInstanceEx [OLE32.165]
1513 HRESULT WINAPI CoCreateInstanceEx(
1515 LPUNKNOWN pUnkOuter,
1517 COSERVERINFO* pServerInfo,
1521 IUnknown* pUnk = NULL;
1524 int successCount = 0;
1529 if ( (cmq==0) || (pResults==NULL))
1530 return E_INVALIDARG;
1532 if (pServerInfo!=NULL)
1533 FIXME("() non-NULL pServerInfo not supported!\n");
1536 * Initialize all the "out" parameters.
1538 for (index = 0; index < cmq; index++)
1540 pResults[index].pItf = NULL;
1541 pResults[index].hr = E_NOINTERFACE;
1545 * Get the object and get its IUnknown pointer.
1547 hr = CoCreateInstance(rclsid,
1557 * Then, query for all the interfaces requested.
1559 for (index = 0; index < cmq; index++)
1561 pResults[index].hr = IUnknown_QueryInterface(pUnk,
1562 pResults[index].pIID,
1563 (VOID**)&(pResults[index].pItf));
1565 if (pResults[index].hr == S_OK)
1570 * Release our temporary unknown pointer.
1572 IUnknown_Release(pUnk);
1574 if (successCount == 0)
1575 return E_NOINTERFACE;
1577 if (successCount!=cmq)
1578 return CO_S_NOTALLINTERFACES;
1583 /***********************************************************************
1584 * CoFreeLibrary [OLE32.13]
1586 void WINAPI CoFreeLibrary(HINSTANCE hLibrary)
1588 OpenDll *ptr, *prev;
1591 EnterCriticalSection( &csOpenDllList );
1593 /* lookup library in linked list */
1595 for (ptr = openDllList; ptr != NULL; ptr=ptr->next) {
1596 if (ptr->hLibrary == hLibrary) {
1603 /* shouldn't happen if user passed in a valid hLibrary */
1606 /* assert: ptr points to the library entry to free */
1608 /* free library and remove node from list */
1609 FreeLibrary(hLibrary);
1610 if (ptr == openDllList) {
1611 tmp = openDllList->next;
1612 HeapFree(GetProcessHeap(), 0, openDllList);
1616 HeapFree(GetProcessHeap(), 0, ptr);
1620 LeaveCriticalSection( &csOpenDllList );
1624 /***********************************************************************
1625 * CoFreeAllLibraries [OLE32.12]
1627 void WINAPI CoFreeAllLibraries(void)
1631 EnterCriticalSection( &csOpenDllList );
1633 for (ptr = openDllList; ptr != NULL; ) {
1635 CoFreeLibrary(ptr->hLibrary);
1639 LeaveCriticalSection( &csOpenDllList );
1644 /***********************************************************************
1645 * CoFreeUnusedLibraries [COMPOBJ.17]
1646 * CoFreeUnusedLibraries [OLE32.14]
1648 void WINAPI CoFreeUnusedLibraries(void)
1651 typedef HRESULT(*DllCanUnloadNowFunc)(void);
1652 DllCanUnloadNowFunc DllCanUnloadNow;
1654 EnterCriticalSection( &csOpenDllList );
1656 for (ptr = openDllList; ptr != NULL; ) {
1657 DllCanUnloadNow = (DllCanUnloadNowFunc)
1658 GetProcAddress(ptr->hLibrary, "DllCanUnloadNow");
1660 if ( (DllCanUnloadNow != NULL) &&
1661 (DllCanUnloadNow() == S_OK) ) {
1663 CoFreeLibrary(ptr->hLibrary);
1670 LeaveCriticalSection( &csOpenDllList );
1673 /***********************************************************************
1674 * CoFileTimeNow [COMPOBJ.82]
1675 * CoFileTimeNow [OLE32.10]
1678 * the current system time in lpFileTime
1680 HRESULT WINAPI CoFileTimeNow( FILETIME *lpFileTime ) /* [out] the current time */
1682 GetSystemTimeAsFileTime( lpFileTime );
1686 /***********************************************************************
1687 * CoTaskMemAlloc (OLE32.43)
1689 * pointer to newly allocated block
1691 LPVOID WINAPI CoTaskMemAlloc(
1692 ULONG size /* [in] size of memoryblock to be allocated */
1695 HRESULT ret = CoGetMalloc(0,&lpmalloc);
1700 return IMalloc_Alloc(lpmalloc,size);
1702 /***********************************************************************
1703 * CoTaskMemFree (OLE32.44)
1705 VOID WINAPI CoTaskMemFree(
1706 LPVOID ptr /* [in] pointer to be freed */
1709 HRESULT ret = CoGetMalloc(0,&lpmalloc);
1714 IMalloc_Free(lpmalloc, ptr);
1717 /***********************************************************************
1718 * CoTaskMemRealloc (OLE32.45)
1720 * pointer to newly allocated block
1722 LPVOID WINAPI CoTaskMemRealloc(
1724 ULONG size) /* [in] size of memoryblock to be allocated */
1727 HRESULT ret = CoGetMalloc(0,&lpmalloc);
1732 return IMalloc_Realloc(lpmalloc, pvOld, size);
1735 /***********************************************************************
1736 * CoLoadLibrary (OLE32.30)
1738 HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree)
1744 TRACE("(%s, %d)\n", debugstr_w(lpszLibName), bAutoFree);
1746 hLibrary = LoadLibraryExW(lpszLibName, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
1751 EnterCriticalSection( &csOpenDllList );
1753 if (openDllList == NULL) {
1754 /* empty list -- add first node */
1755 openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
1756 openDllList->hLibrary=hLibrary;
1757 openDllList->next = NULL;
1759 /* search for this dll */
1761 for (ptr = openDllList; ptr->next != NULL; ptr=ptr->next) {
1762 if (ptr->hLibrary == hLibrary) {
1768 /* dll not found, add it */
1770 openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
1771 openDllList->hLibrary = hLibrary;
1772 openDllList->next = tmp;
1776 LeaveCriticalSection( &csOpenDllList );
1781 /***********************************************************************
1782 * CoInitializeWOW (OLE32.27)
1784 HRESULT WINAPI CoInitializeWOW(DWORD x,DWORD y) {
1785 FIXME("(0x%08lx,0x%08lx),stub!\n",x,y);
1789 /******************************************************************************
1790 * CoLockObjectExternal [COMPOBJ.63]
1792 HRESULT WINAPI CoLockObjectExternal16(
1793 LPUNKNOWN pUnk, /* [in] object to be locked */
1794 BOOL16 fLock, /* [in] do lock */
1795 BOOL16 fLastUnlockReleases /* [in] ? */
1797 FIXME("(%p,%d,%d),stub!\n",pUnk,fLock,fLastUnlockReleases);
1801 /******************************************************************************
1802 * CoLockObjectExternal [OLE32.31]
1804 HRESULT WINAPI CoLockObjectExternal(
1805 LPUNKNOWN pUnk, /* [in] object to be locked */
1806 BOOL fLock, /* [in] do lock */
1807 BOOL fLastUnlockReleases) /* [in] unlock all */
1813 * Increment the external lock coutner, COM_ExternalLockAddRef also
1814 * increment the object's internal lock counter.
1816 COM_ExternalLockAddRef( pUnk);
1821 * Decrement the external lock coutner, COM_ExternalLockRelease also
1822 * decrement the object's internal lock counter.
1824 COM_ExternalLockRelease( pUnk, fLastUnlockReleases);
1830 /***********************************************************************
1831 * CoGetState [COMPOBJ.115]
1833 HRESULT WINAPI CoGetState16(LPDWORD state)
1835 FIXME("(%p),stub!\n", state);
1839 /***********************************************************************
1840 * CoSetState [OLE32.42]
1842 HRESULT WINAPI CoSetState(LPDWORD state)
1844 FIXME("(%p),stub!\n", state);
1845 if (state) *state = 0;
1848 /***********************************************************************
1849 * CoCreateFreeThreadedMarshaler [OLE32.5]
1851 HRESULT WINAPI CoCreateFreeThreadedMarshaler (LPUNKNOWN punkOuter, LPUNKNOWN* ppunkMarshal)
1853 FIXME ("(%p %p): stub\n", punkOuter, ppunkMarshal);
1859 /***********************************************************************
1860 * DllGetClassObject [OLE32.63]
1862 HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
1864 FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
1866 return CLASS_E_CLASSNOTAVAILABLE;
1871 * COM_RevokeAllClasses
1873 * This method is called when the COM libraries are uninitialized to
1874 * release all the references to the class objects registered with
1877 static void COM_RevokeAllClasses()
1879 EnterCriticalSection( &csRegisteredClassList );
1881 while (firstRegisteredClass!=0)
1883 CoRevokeClassObject(firstRegisteredClass->dwCookie);
1886 LeaveCriticalSection( &csRegisteredClassList );
1889 /****************************************************************************
1890 * COM External Lock methods implementation
1893 /****************************************************************************
1894 * Public - Method that increments the count for a IUnknown* in the linked
1895 * list. The item is inserted if not already in the list.
1897 static void COM_ExternalLockAddRef(
1900 COM_ExternalLock *externalLock = COM_ExternalLockFind(pUnk);
1903 * Add an external lock to the object. If it was already externally
1904 * locked, just increase the reference count. If it was not.
1905 * add the item to the list.
1907 if ( externalLock == EL_NOT_FOUND )
1908 COM_ExternalLockInsert(pUnk);
1910 externalLock->uRefCount++;
1913 * Add an internal lock to the object
1915 IUnknown_AddRef(pUnk);
1918 /****************************************************************************
1919 * Public - Method that decrements the count for a IUnknown* in the linked
1920 * list. The item is removed from the list if its count end up at zero or if
1923 static void COM_ExternalLockRelease(
1927 COM_ExternalLock *externalLock = COM_ExternalLockFind(pUnk);
1929 if ( externalLock != EL_NOT_FOUND )
1933 externalLock->uRefCount--; /* release external locks */
1934 IUnknown_Release(pUnk); /* release local locks as well */
1936 if ( bRelAll == FALSE )
1937 break; /* perform single release */
1939 } while ( externalLock->uRefCount > 0 );
1941 if ( externalLock->uRefCount == 0 ) /* get rid of the list entry */
1942 COM_ExternalLockDelete(externalLock);
1945 /****************************************************************************
1946 * Public - Method that frees the content of the list.
1948 static void COM_ExternalLockFreeList()
1950 COM_ExternalLock *head;
1952 head = elList.head; /* grab it by the head */
1953 while ( head != EL_END_OF_LIST )
1955 COM_ExternalLockDelete(head); /* get rid of the head stuff */
1957 head = elList.head; /* get the new head... */
1961 /****************************************************************************
1962 * Public - Method that dump the content of the list.
1964 void COM_ExternalLockDump()
1966 COM_ExternalLock *current = elList.head;
1968 DPRINTF("\nExternal lock list contains:\n");
1970 while ( current != EL_END_OF_LIST )
1972 DPRINTF( "\t%p with %lu references count.\n", current->pUnk, current->uRefCount);
1974 /* Skip to the next item */
1975 current = current->next;
1980 /****************************************************************************
1981 * Internal - Find a IUnknown* in the linked list
1983 static COM_ExternalLock* COM_ExternalLockFind(
1986 return COM_ExternalLockLocate(elList.head, pUnk);
1989 /****************************************************************************
1990 * Internal - Recursivity agent for IUnknownExternalLockList_Find
1992 static COM_ExternalLock* COM_ExternalLockLocate(
1993 COM_ExternalLock *element,
1996 if ( element == EL_END_OF_LIST )
1997 return EL_NOT_FOUND;
1999 else if ( element->pUnk == pUnk ) /* We found it */
2002 else /* Not the right guy, keep on looking */
2003 return COM_ExternalLockLocate( element->next, pUnk);
2006 /****************************************************************************
2007 * Internal - Insert a new IUnknown* to the linked list
2009 static BOOL COM_ExternalLockInsert(
2012 COM_ExternalLock *newLock = NULL;
2013 COM_ExternalLock *previousHead = NULL;
2016 * Allocate space for the new storage object
2018 newLock = HeapAlloc(GetProcessHeap(), 0, sizeof(COM_ExternalLock));
2022 if ( elList.head == EL_END_OF_LIST )
2024 elList.head = newLock; /* The list is empty */
2029 * insert does it at the head
2031 previousHead = elList.head;
2032 elList.head = newLock;
2036 * Set new list item data member
2038 newLock->pUnk = pUnk;
2039 newLock->uRefCount = 1;
2040 newLock->next = previousHead;
2048 /****************************************************************************
2049 * Internal - Method that removes an item from the linked list.
2051 static void COM_ExternalLockDelete(
2052 COM_ExternalLock *itemList)
2054 COM_ExternalLock *current = elList.head;
2056 if ( current == itemList )
2059 * this section handles the deletion of the first node
2061 elList.head = itemList->next;
2062 HeapFree( GetProcessHeap(), 0, itemList);
2068 if ( current->next == itemList ) /* We found the item to free */
2070 current->next = itemList->next; /* readjust the list pointers */
2072 HeapFree( GetProcessHeap(), 0, itemList);
2076 /* Skip to the next item */
2077 current = current->next;
2079 } while ( current != EL_END_OF_LIST );
2083 /***********************************************************************
2084 * DllEntryPoint [COMPOBJ.116]
2086 * Initialization code for the COMPOBJ DLL
2090 BOOL WINAPI COMPOBJ_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst, WORD ds, WORD HeapSize, DWORD res1, WORD res2)
2092 TRACE("(%08lx, %04x, %04x, %04x, %08lx, %04x)\n", Reason, hInst, ds, HeapSize,
2096 case DLL_PROCESS_ATTACH:
2097 if (!COMPOBJ_Attach++) COMPOBJ_hInstance = hInst;
2100 case DLL_PROCESS_DETACH:
2101 if(!--COMPOBJ_Attach)
2102 COMPOBJ_hInstance = 0;
2108 /******************************************************************************
2109 * OleGetAutoConvert [OLE32.104]
2111 HRESULT WINAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew)
2119 sprintf(buf,"CLSID\\");WINE_StringFromCLSID(clsidOld,&buf[6]);
2120 if (RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&hkey))
2122 res = REGDB_E_CLASSNOTREG;
2126 /* we can just query for the default value of AutoConvertTo key like that,
2127 without opening the AutoConvertTo key and querying for NULL (default) */
2128 if (RegQueryValueA(hkey,"AutoConvertTo",buf,&len))
2130 res = REGDB_E_KEYMISSING;
2133 MultiByteToWideChar( CP_ACP, 0, buf, -1, wbuf, sizeof(wbuf)/sizeof(WCHAR) );
2134 CLSIDFromString(wbuf,pClsidNew);
2136 if (hkey) RegCloseKey(hkey);
2141 /******************************************************************************
2142 * OleSetAutoConvert [OLE32.126]
2144 HRESULT WINAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew)
2147 char buf[200], szClsidNew[200];
2150 TRACE("(%s,%s)\n", debugstr_guid(clsidOld), debugstr_guid(clsidNew));
2151 sprintf(buf,"CLSID\\");WINE_StringFromCLSID(clsidOld,&buf[6]);
2152 WINE_StringFromCLSID(clsidNew, szClsidNew);
2153 if (RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&hkey))
2155 res = REGDB_E_CLASSNOTREG;
2158 if (RegSetValueA(hkey, "AutoConvertTo", REG_SZ, szClsidNew, strlen(szClsidNew)+1))
2160 res = REGDB_E_WRITEREGDB;
2165 if (hkey) RegCloseKey(hkey);
2169 /******************************************************************************
2170 * CoTreatAsClass [OLE32.46]
2172 HRESULT WINAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew)
2175 char buf[200], szClsidNew[200];
2178 FIXME("(%s,%s)\n", debugstr_guid(clsidOld), debugstr_guid(clsidNew));
2179 sprintf(buf,"CLSID\\");WINE_StringFromCLSID(clsidOld,&buf[6]);
2180 WINE_StringFromCLSID(clsidNew, szClsidNew);
2181 if (RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&hkey))
2183 res = REGDB_E_CLASSNOTREG;
2186 if (RegSetValueA(hkey, "AutoTreatAs", REG_SZ, szClsidNew, strlen(szClsidNew)+1))
2188 res = REGDB_E_WRITEREGDB;
2193 if (hkey) RegCloseKey(hkey);
2198 /***********************************************************************
2199 * IsEqualGUID [OLE32.76]
2201 * Compares two Unique Identifiers.
2207 BOOL WINAPI IsEqualGUID(
2208 REFGUID rguid1, /* [in] unique id 1 */
2209 REFGUID rguid2 /* [in] unique id 2 */
2212 return !memcmp(rguid1,rguid2,sizeof(GUID));