source: trunk/src/ole32/compobj.c@ 7355

Last change on this file since 7355 was 7355, checked in by phaller, 24 years ago

Accelerated CLSID functions

File size: 55.1 KB
Line 
1/*
2 * COMPOBJ library
3 *
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1998 Justin Bradford
6 * Copyright 1999 Francis Beaudet
7 * Copyright 1999 Sylvain St-Germain
8 */
9
10#include "config.h"
11
12#include <stdlib.h>
13#include <stdio.h>
14#include <string.h>
15#include <assert.h>
16#include "windef.h"
17#include "wtypes.h"
18#include "wingdi.h"
19#include "wine/winbase16.h"
20#include "winerror.h"
21#include "wownt32.h"
22#include "ole2ver.h"
23#include "debugtools.h"
24#include "heap.h"
25#include "winreg.h"
26#include "rpc.h"
27
28#include "wine/obj_base.h"
29#include "wine/obj_misc.h"
30#include "wine/obj_storage.h"
31#include "wine/obj_clientserver.h"
32
33#include "ole.h"
34#include "ifs.h"
35#include "compobj_private.h"
36
37#ifdef __WIN32OS2__
38#include <heapstring.h>
39
40#undef FIXME
41#undef TRACE
42#ifdef DEBUG
43#define TRACE WriteLog("OLE32: %s", __FUNCTION__); WriteLog
44#define FIXME WriteLog("FIXME OLE32: %s", __FUNCTION__); WriteLog
45#else
46#define TRACE 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
47#define FIXME 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
48#endif
49#endif
50
51DEFAULT_DEBUG_CHANNEL(ole);
52
53/****************************************************************************
54 * COM External Lock structures and methods declaration
55 *
56 * This api provides a linked list to managed external references to
57 * COM objects.
58 *
59 * The public interface consists of three calls:
60 * COM_ExternalLockAddRef
61 * COM_ExternalLockRelease
62 * COM_ExternalLockFreeList
63 */
64
65#define EL_END_OF_LIST 0
66#define EL_NOT_FOUND 0
67
68/*
69 * Declaration of the static structure that manage the
70 * external lock to COM objects.
71 */
72typedef struct COM_ExternalLock COM_ExternalLock;
73typedef struct COM_ExternalLockList COM_ExternalLockList;
74
75struct COM_ExternalLock
76{
77 IUnknown *pUnk; /* IUnknown referenced */
78 ULONG uRefCount; /* external lock counter to IUnknown object*/
79 COM_ExternalLock *next; /* Pointer to next element in list */
80};
81
82struct COM_ExternalLockList
83{
84 COM_ExternalLock *head; /* head of list */
85};
86
87/*
88 * Declaration and initialization of the static structure that manages
89 * the external lock to COM objects.
90 */
91static COM_ExternalLockList elList = { EL_END_OF_LIST };
92
93/*
94 * Public Interface to the external lock list
95 */
96static void COM_ExternalLockFreeList();
97static void COM_ExternalLockAddRef(IUnknown *pUnk);
98static void COM_ExternalLockRelease(IUnknown *pUnk, BOOL bRelAll);
99void COM_ExternalLockDump(); /* testing purposes, not static to avoid warning */
100
101/*
102 * Private methods used to managed the linked list
103 */
104static BOOL COM_ExternalLockInsert(
105 IUnknown *pUnk);
106
107static void COM_ExternalLockDelete(
108 COM_ExternalLock *element);
109
110static COM_ExternalLock* COM_ExternalLockFind(
111 IUnknown *pUnk);
112
113static COM_ExternalLock* COM_ExternalLockLocate(
114 COM_ExternalLock *element,
115 IUnknown *pUnk);
116
117/****************************************************************************
118 * This section defines variables internal to the COM module.
119 *
120 * TODO: Most of these things will have to be made thread-safe.
121 */
122HINSTANCE16 COMPOBJ_hInstance = 0;
123HINSTANCE COMPOBJ_hInstance32 = 0;
124static int COMPOBJ_Attach = 0;
125
126LPMALLOC16 currentMalloc16=NULL;
127LPMALLOC currentMalloc32=NULL;
128
129HTASK16 hETask = 0;
130WORD Table_ETask[62];
131
132/*
133 * This lock count counts the number of times CoInitialize is called. It is
134 * decreased every time CoUninitialize is called. When it hits 0, the COM
135 * libraries are freed
136 */
137static ULONG s_COMLockCount = 0;
138
139/*
140 * This linked list contains the list of registered class objects. These
141 * are mostly used to register the factories for out-of-proc servers of OLE
142 * objects.
143 *
144 * TODO: Make this data structure aware of inter-process communication. This
145 * means that parts of this will be exported to the Wine Server.
146 */
147typedef struct tagRegisteredClass
148{
149 CLSID classIdentifier;
150 LPUNKNOWN classObject;
151 DWORD runContext;
152 DWORD connectFlags;
153 DWORD dwCookie;
154 struct tagRegisteredClass* nextClass;
155} RegisteredClass;
156
157static RegisteredClass* firstRegisteredClass = NULL;
158
159/* this open DLL table belongs in a per process table, but my guess is that
160 * it shouldn't live in the kernel, so I'll put them out here in DLL
161 * space assuming that there is one OLE32 per process.
162 */
163typedef struct tagOpenDll {
164 HINSTANCE hLibrary;
165 struct tagOpenDll *next;
166} OpenDll;
167
168static OpenDll *openDllList = NULL; /* linked list of open dlls */
169
170/*****************************************************************************
171 * This section contains prototypes to internal methods for this
172 * module
173 */
174static HRESULT COM_GetRegisteredClassObject(REFCLSID rclsid,
175 DWORD dwClsContext,
176 LPUNKNOWN* ppUnk);
177
178static void COM_RevokeAllClasses();
179
180
181/******************************************************************************
182 * CoBuildVersion [COMPOBJ.1]
183 *
184 * RETURNS
185 * Current build version, hiword is majornumber, loword is minornumber
186 */
187DWORD WINAPI CoBuildVersion(void)
188{
189 TRACE("Returning version %d, build %d.\n", rmm, rup);
190 return (rmm<<16)+rup;
191}
192
193#ifndef __WIN32OS2__
194/******************************************************************************
195 * CoInitialize16 [COMPOBJ.2]
196 * Set the win16 IMalloc used for memory management
197 */
198HRESULT WINAPI CoInitialize16(
199 LPVOID lpReserved /* [in] pointer to win16 malloc interface */
200) {
201 currentMalloc16 = (LPMALLOC16)lpReserved;
202 return S_OK;
203}
204#endif
205
206/******************************************************************************
207 * CoInitialize [OLE32.26]
208 *
209 * Initializes the COM libraries.
210 *
211 * See CoInitializeEx
212 */
213HRESULT WINAPI CoInitialize(
214 LPVOID lpReserved /* [in] pointer to win32 malloc interface
215 (obsolete, should be NULL) */
216)
217{
218 /*
219 * Just delegate to the newer method.
220 */
221 return CoInitializeEx(lpReserved, COINIT_APARTMENTTHREADED);
222}
223
224/******************************************************************************
225 * CoInitializeEx [OLE32.163]
226 *
227 * Initializes the COM libraries. The behavior used to set the win32 IMalloc
228 * used for memory management is obsolete.
229 *
230 * RETURNS
231 * S_OK if successful,
232 * S_FALSE if this function was called already.
233 * RPC_E_CHANGED_MODE if a previous call to CoInitialize specified another
234 * threading model.
235 *
236 * BUGS
237 * Only the single threaded model is supported. As a result RPC_E_CHANGED_MODE
238 * is never returned.
239 *
240 * See the windows documentation for more details.
241 */
242HRESULT WINAPI CoInitializeEx(
243 LPVOID lpReserved, /* [in] pointer to win32 malloc interface
244 (obsolete, should be NULL) */
245 DWORD dwCoInit /* [in] A value from COINIT specifies the threading model */
246)
247{
248 HRESULT hr;
249
250 TRACE("(%p, %x)\n", lpReserved, (int)dwCoInit);
251
252 if (lpReserved!=NULL)
253 {
254 ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved);
255 }
256
257 /*
258 * Check for unsupported features.
259 */
260 if (dwCoInit!=COINIT_APARTMENTTHREADED)
261 {
262 FIXME(":(%p,%x): unsupported flag %x\n", lpReserved, (int)dwCoInit, (int)dwCoInit);
263 /* Hope for the best and continue anyway */
264 }
265
266 /*
267 * Check the lock count. If this is the first time going through the initialize
268 * process, we have to initialize the libraries.
269 */
270 if (s_COMLockCount==0)
271 {
272 /*
273 * Initialize the various COM libraries and data structures.
274 */
275 TRACE("() - Initializing the COM libraries\n");
276
277 RunningObjectTableImpl_Initialize();
278
279 hr = S_OK;
280 }
281 else
282 hr = S_FALSE;
283
284 /*
285 * Crank-up that lock count.
286 */
287 s_COMLockCount++;
288
289 return hr;
290}
291
292#ifndef __WIN32OS2__
293/***********************************************************************
294 * CoUninitialize16 [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
298 */
299void WINAPI CoUninitialize16(void)
300{
301 TRACE("()\n");
302 CoFreeAllLibraries();
303}
304#endif
305
306/***********************************************************************
307 * CoUninitialize [OLE32.47]
308 *
309 * This method will release the COM libraries.
310 *
311 * See the windows documentation for more details.
312 */
313void WINAPI CoUninitialize(void)
314{
315 TRACE("()\n");
316
317 /*
318 * Decrease the reference count.
319 */
320 s_COMLockCount--;
321
322 /*
323 * If we are back to 0 locks on the COM library, make sure we free
324 * all the associated data structures.
325 */
326 if (s_COMLockCount==0)
327 {
328 /*
329 * Release the various COM libraries and data structures.
330 */
331 TRACE("() - Releasing the COM libraries\n");
332
333 RunningObjectTableImpl_UnInitialize();
334 /*
335 * Release the references to the registered class objects.
336 */
337 COM_RevokeAllClasses();
338
339 /*
340 * This will free the loaded COM Dlls.
341 */
342 CoFreeAllLibraries();
343
344 /*
345 * This will free list of external references to COM objects.
346 */
347 COM_ExternalLockFreeList();
348}
349}
350
351#ifndef __WIN32OS2__
352/***********************************************************************
353 * CoGetMalloc16 [COMPOBJ.4]
354 * RETURNS
355 * The current win16 IMalloc
356 */
357HRESULT WINAPI CoGetMalloc16(
358 DWORD dwMemContext, /* [in] unknown */
359 LPMALLOC16 * lpMalloc /* [out] current win16 malloc interface */
360) {
361 if(!currentMalloc16)
362 currentMalloc16 = IMalloc16_Constructor();
363 *lpMalloc = currentMalloc16;
364 return S_OK;
365}
366#endif
367
368/******************************************************************************
369 * CoGetMalloc [OLE32.20]
370 *
371 * RETURNS
372 * The current win32 IMalloc
373 */
374HRESULT WINAPI CoGetMalloc(
375 DWORD dwMemContext, /* [in] unknown */
376 LPMALLOC *lpMalloc /* [out] current win32 malloc interface */
377) {
378 if(!currentMalloc32)
379 currentMalloc32 = IMalloc_Constructor();
380 *lpMalloc = currentMalloc32;
381 return S_OK;
382}
383
384#ifndef __WIN32OS2__
385/***********************************************************************
386 * CoCreateStandardMalloc16 [COMPOBJ.71]
387 */
388HRESULT WINAPI CoCreateStandardMalloc16(DWORD dwMemContext,
389 LPMALLOC16 *lpMalloc)
390{
391 /* FIXME: docu says we shouldn't return the same allocator as in
392 * CoGetMalloc16 */
393 *lpMalloc = IMalloc16_Constructor();
394 return S_OK;
395}
396
397/******************************************************************************
398 * CoDisconnectObject [COMPOBJ.15]
399 */
400HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved )
401{
402 TRACE("(%p, %lx)\n",lpUnk,reserved);
403 return S_OK;
404}
405
406/***********************************************************************
407 * IsEqualGUID16 [COMPOBJ.18]
408 *
409 * Compares two Unique Identifiers.
410 *
411 * RETURNS
412 * TRUE if equal
413 */
414BOOL16 WINAPI IsEqualGUID16(
415 GUID* g1, /* [in] unique id 1 */
416 GUID* g2 /* [in] unique id 2 */
417) {
418 return !memcmp( g1, g2, sizeof(GUID) );
419}
420#endif
421
422/******************************************************************************
423 * CLSIDFromString16 [COMPOBJ.20]
424 * Converts a unique identifier from its string representation into
425 * the GUID struct.
426 *
427 * Class id: DWORD-WORD-WORD-BYTES[2]-BYTES[6]
428 *
429 * RETURNS
430 * the converted GUID
431 */
432HRESULT WINAPI CLSIDFromString16(
433 LPCOLESTR16 idstr, /* [in] string representation of guid */
434 CLSID *id /* [out] GUID converted from string */
435) {
436 BYTE *s = (BYTE *) idstr;
437 BYTE *p;
438 int i;
439
440
441#ifdef __WIN32OS2__
442 // Note: only setup the lookup table once!
443 static BOOL fCLSIDTableInitialized = FALSE;
444 static BYTE table[256];
445#else
446 BYTE table[256];
447#endif
448
449 if (!s)
450 s = "{00000000-0000-0000-0000-000000000000}";
451 else { /* validate the CLSID string */
452
453#ifdef __WIN32OS2__
454 // PH: all other characters are tested up to the 38th
455 // and cannot be zero so this test should be sufficient.
456 if (s[38] != 0)
457#else
458 if (strlen(s) != 38)
459#endif
460 return CO_E_CLASSSTRING;
461
462 if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') || (s[24]!='-') || (s[37]!='}'))
463 return CO_E_CLASSSTRING;
464
465 for (i=1; i<37; i++)
466 {
467 if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue;
468 if (!(((s[i] >= '0') && (s[i] <= '9')) ||
469 ((s[i] >= 'a') && (s[i] <= 'f')) ||
470 ((s[i] >= 'A') && (s[i] <= 'F')))
471 )
472 return CO_E_CLASSSTRING;
473 }
474 }
475
476 TRACE("%s -> %p\n", s, id);
477
478
479#ifdef __WIN32OS2__
480 if (fCLSIDTableInitialized == FALSE)
481 {
482 fCLSIDTableInitialized = TRUE;
483#endif
484
485 /* quick lookup table */
486 memset(table, 0, 256);
487
488 for (i = 0; i < 10; i++) {
489 table['0' + i] = i;
490 }
491 for (i = 0; i < 6; i++) {
492 table['A' + i] = i+10;
493 table['a' + i] = i+10;
494 }
495
496#ifdef __WIN32OS2__
497 }
498#endif
499
500 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
501
502 p = (BYTE *) id;
503
504 s++; /* skip leading brace */
505 for (i = 0; i < 4; i++) {
506 p[3 - i] = table[*s]<<4 | table[*(s+1)];
507 s += 2;
508 }
509 p += 4;
510 s++; /* skip - */
511
512 for (i = 0; i < 2; i++) {
513 p[1-i] = table[*s]<<4 | table[*(s+1)];
514 s += 2;
515 }
516 p += 2;
517 s++; /* skip - */
518
519 for (i = 0; i < 2; i++) {
520 p[1-i] = table[*s]<<4 | table[*(s+1)];
521 s += 2;
522 }
523 p += 2;
524 s++; /* skip - */
525
526 /* these are just sequential bytes */
527 for (i = 0; i < 2; i++) {
528 *p++ = table[*s]<<4 | table[*(s+1)];
529 s += 2;
530 }
531 s++; /* skip - */
532
533 for (i = 0; i < 6; i++) {
534 *p++ = table[*s]<<4 | table[*(s+1)];
535 s += 2;
536 }
537
538 return S_OK;
539}
540
541/******************************************************************************
542 * CoCreateGuid[OLE32.6]
543 *
544 */
545HRESULT WINAPI CoCreateGuid(
546 GUID *pguid /* [out] points to the GUID to initialize */
547) {
548 return UuidCreate(pguid);
549}
550
551/******************************************************************************
552 * CLSIDFromString [OLE32.3]
553 * Converts a unique identifier from its string representation into
554 * the GUID struct.
555 *
556 * UNDOCUMENTED
557 * If idstr is not a valid CLSID string then it gets treated as a ProgID
558 *
559 * RETURNS
560 * the converted GUID
561 */
562HRESULT WINAPI CLSIDFromString(
563 LPCOLESTR idstr, /* [in] string representation of GUID */
564 CLSID *id /* [out] GUID represented by above string */
565) {
566 LPOLESTR16 xid = HEAP_strdupWtoA(GetProcessHeap(),0,idstr);
567 HRESULT ret = CLSIDFromString16(xid,id);
568
569 HeapFree(GetProcessHeap(),0,xid);
570 if(ret != S_OK) { /* It appears a ProgID is also valid */
571 ret = CLSIDFromProgID(idstr, id);
572 }
573 return ret;
574}
575
576/******************************************************************************
577 * WINE_StringFromCLSID [Internal]
578 * Converts a GUID into the respective string representation.
579 *
580 * NOTES
581 *
582 * RETURNS
583 * the string representation and HRESULT
584 */
585#ifdef __WIN32OS2__
586HRESULT WINAPI WINE_StringFromCLSID(
587 const CLSID *id, /* [in] GUID to be converted */
588 LPSTR idstr /* [out] pointer to buffer to contain converted guid */
589#else
590static HRESULT WINE_StringFromCLSID(
591 const CLSID *id, /* [in] GUID to be converted */
592 LPSTR idstr /* [out] pointer to buffer to contain converted guid */
593#endif
594) {
595 static const char *hex = "0123456789ABCDEF";
596 char *s;
597 int i;
598
599 if (!id)
600 { ERR("called with id=Null\n");
601 *idstr = 0x00;
602 return E_FAIL;
603 }
604
605 sprintf(idstr, "{%08lX-%04X-%04X-%02X%02X-",
606 id->Data1, id->Data2, id->Data3,
607 id->Data4[0], id->Data4[1]);
608 s = &idstr[25];
609
610 /* 6 hex bytes */
611 for (i = 2; i < 8; i++) {
612 *s++ = hex[id->Data4[i]>>4];
613 *s++ = hex[id->Data4[i] & 0xf];
614 }
615
616 *s++ = '}';
617 *s++ = '\0';
618
619 TRACE("%p->%s\n", id, idstr);
620
621 return S_OK;
622}
623#ifndef __WIN32OS2__
624/******************************************************************************
625 * StringFromCLSID16 [COMPOBJ.19]
626 * Converts a GUID into the respective string representation.
627 * The target string is allocated using the OLE IMalloc.
628 * RETURNS
629 * the string representation and HRESULT
630 */
631HRESULT WINAPI StringFromCLSID16(
632 REFCLSID id, /* [in] the GUID to be converted */
633 LPOLESTR16 *idstr /* [out] a pointer to a to-be-allocated segmented pointer pointing to the resulting string */
634
635) {
636 extern BOOL WINAPI K32WOWCallback16Ex( DWORD vpfn16, DWORD dwFlags,
637 DWORD cbArgs, LPVOID pArgs, LPDWORD pdwRetCode );
638 LPMALLOC16 mllc;
639 HRESULT ret;
640 DWORD args[2];
641
642 ret = CoGetMalloc16(0,&mllc);
643 if (ret) return ret;
644
645 args[0] = (DWORD)mllc;
646 args[1] = 40;
647
648 /* No need for a Callback entry, we have WOWCallback16Ex which does
649 * everything we need.
650 */
651 if (!K32WOWCallback16Ex(
652 (DWORD)((ICOM_VTABLE(IMalloc16)*)MapSL(
653 (SEGPTR)ICOM_VTBL(((LPMALLOC16)MapSL((SEGPTR)mllc))))
654 )->Alloc,
655 WCB16_CDECL,
656 2*sizeof(DWORD),
657 (LPVOID)args,
658 (LPDWORD)idstr
659 )) {
660 WARN("CallTo16 IMalloc16 failed\n");
661 return E_FAIL;
662 }
663 return WINE_StringFromCLSID(id,MapSL((SEGPTR)*idstr));
664}
665#endif
666/******************************************************************************
667 * StringFromCLSID [OLE32.151]
668 * Converts a GUID into the respective string representation.
669 * The target string is allocated using the OLE IMalloc.
670 * RETURNS
671 * the string representation and HRESULT
672 */
673HRESULT WINAPI StringFromCLSID(
674 REFCLSID id, /* [in] the GUID to be converted */
675 LPOLESTR *idstr /* [out] a pointer to a to-be-allocated pointer pointing to the resulting string */
676) {
677 char buf[80];
678 HRESULT ret;
679 LPMALLOC mllc;
680
681 if ((ret=CoGetMalloc(0,&mllc)))
682 return ret;
683
684 ret=WINE_StringFromCLSID(id,buf);
685 if (!ret) {
686 DWORD len = MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 );
687 *idstr = IMalloc_Alloc( mllc, len * sizeof(WCHAR) );
688 MultiByteToWideChar( CP_ACP, 0, buf, -1, *idstr, len );
689 }
690 return ret;
691}
692
693/******************************************************************************
694 * StringFromGUID2 [COMPOBJ.76] [OLE32.152]
695 *
696 * Converts a global unique identifier into a string of an API-
697 * specified fixed format. (The usual {.....} stuff.)
698 *
699 * RETURNS
700 * The (UNICODE) string representation of the GUID in 'str'
701 * The length of the resulting string, 0 if there was any problem.
702 */
703INT WINAPI
704StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
705{
706 char xguid[80];
707
708 if (WINE_StringFromCLSID(id,xguid))
709 return 0;
710 return MultiByteToWideChar( CP_ACP, 0, xguid, -1, str, cmax );
711}
712
713/******************************************************************************
714 * ProgIDFromCLSID [OLE32.133]
715 * Converts a class id into the respective Program ID. (By using a registry lookup)
716 * RETURNS S_OK on success
717 * riid associated with the progid
718 */
719
720HRESULT WINAPI ProgIDFromCLSID(
721 REFCLSID clsid, /* [in] class id as found in registry */
722 LPOLESTR *lplpszProgID/* [out] associated Prog ID */
723)
724{
725 char strCLSID[50], *buf, *buf2;
726 DWORD buf2len;
727 HKEY xhkey;
728 LPMALLOC mllc;
729 HRESULT ret = S_OK;
730
731 WINE_StringFromCLSID(clsid, strCLSID);
732
733 buf = HeapAlloc(GetProcessHeap(), 0, strlen(strCLSID)+14);
734 sprintf(buf,"CLSID\\%s\\ProgID", strCLSID);
735 if (RegOpenKeyA(HKEY_CLASSES_ROOT, buf, &xhkey))
736 ret = REGDB_E_CLASSNOTREG;
737
738 HeapFree(GetProcessHeap(), 0, buf);
739
740 if (ret == S_OK)
741 {
742 buf2 = HeapAlloc(GetProcessHeap(), 0, 255);
743 buf2len = 255;
744 if (RegQueryValueA(xhkey, NULL, buf2, &buf2len))
745 ret = REGDB_E_CLASSNOTREG;
746
747 if (ret == S_OK)
748 {
749 if (CoGetMalloc(0,&mllc))
750 ret = E_OUTOFMEMORY;
751 else
752 {
753 DWORD len = MultiByteToWideChar( CP_ACP, 0, buf2, -1, NULL, 0 );
754 *lplpszProgID = IMalloc_Alloc(mllc, len * sizeof(WCHAR) );
755 MultiByteToWideChar( CP_ACP, 0, buf2, -1, *lplpszProgID, len );
756 }
757 }
758 HeapFree(GetProcessHeap(), 0, buf2);
759 }
760
761 RegCloseKey(xhkey);
762 return ret;
763}
764
765/******************************************************************************
766 * CLSIDFromProgID16 [COMPOBJ.61]
767 * Converts a program id into the respective GUID. (By using a registry lookup)
768 * RETURNS
769 * riid associated with the progid
770 */
771HRESULT WINAPI CLSIDFromProgID16(
772 LPCOLESTR16 progid, /* [in] program id as found in registry */
773 LPCLSID riid /* [out] associated CLSID */
774) {
775 char *buf,buf2[80];
776 DWORD buf2len;
777 HRESULT err;
778 HKEY xhkey;
779
780 buf = HeapAlloc(GetProcessHeap(),0,strlen(progid)+8);
781 sprintf(buf,"%s\\CLSID",progid);
782 if ((err=RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&xhkey))) {
783 HeapFree(GetProcessHeap(),0,buf);
784 return CO_E_CLASSSTRING;
785 }
786 HeapFree(GetProcessHeap(),0,buf);
787 buf2len = sizeof(buf2);
788 if ((err=RegQueryValueA(xhkey,NULL,buf2,&buf2len))) {
789 RegCloseKey(xhkey);
790 return CO_E_CLASSSTRING;
791 }
792 RegCloseKey(xhkey);
793 return CLSIDFromString16(buf2,riid);
794}
795
796/******************************************************************************
797 * CLSIDFromProgID [OLE32.2]
798 * Converts a program id into the respective GUID. (By using a registry lookup)
799 * RETURNS
800 * riid associated with the progid
801 */
802HRESULT WINAPI CLSIDFromProgID(
803 LPCOLESTR progid, /* [in] program id as found in registry */
804 LPCLSID riid /* [out] associated CLSID */
805) {
806 LPOLESTR16 pid = HEAP_strdupWtoA(GetProcessHeap(),0,progid);
807 HRESULT ret = CLSIDFromProgID16(pid,riid);
808
809 HeapFree(GetProcessHeap(),0,pid);
810 return ret;
811}
812
813
814
815/*****************************************************************************
816 * CoGetPSClsid [OLE32.22]
817 *
818 * This function returns the CLSID of the DLL that implements the proxy and stub
819 * for the specified interface.
820 *
821 * It determines this by searching the
822 * HKEY_CLASSES_ROOT\Interface\{string form of riid}\ProxyStubClsid32 in the registry
823 * and any interface id registered by CoRegisterPSClsid within the current process.
824 *
825 * FIXME: We only search the registry, not ids registered with CoRegisterPSClsid.
826 */
827HRESULT WINAPI CoGetPSClsid(
828 REFIID riid, /* [in] Interface whose proxy/stub CLSID is to be returned */
829 CLSID *pclsid ) /* [out] Where to store returned proxy/stub CLSID */
830{
831 char *buf, buf2[40];
832 DWORD buf2len;
833 HKEY xhkey;
834
835 TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid), pclsid);
836
837 /* Get the input iid as a string */
838 WINE_StringFromCLSID(riid, buf2);
839 /* Allocate memory for the registry key we will construct.
840 (length of iid string plus constant length of static text */
841 buf = HeapAlloc(GetProcessHeap(), 0, strlen(buf2)+27);
842 if (buf == NULL)
843 {
844 return (E_OUTOFMEMORY);
845 }
846
847 /* Construct the registry key we want */
848 sprintf(buf,"Interface\\%s\\ProxyStubClsid32", buf2);
849
850 /* Open the key.. */
851 if (RegOpenKeyA(HKEY_CLASSES_ROOT, buf, &xhkey))
852 {
853 HeapFree(GetProcessHeap(),0,buf);
854 return (E_INVALIDARG);
855 }
856 HeapFree(GetProcessHeap(),0,buf);
857
858 /* ... Once we have the key, query the registry to get the
859 value of CLSID as a string, and convert it into a
860 proper CLSID structure to be passed back to the app */
861 buf2len = sizeof(buf2);
862 if ( (RegQueryValueA(xhkey,NULL,buf2,&buf2len)) )
863 {
864 RegCloseKey(xhkey);
865 return E_INVALIDARG;
866 }
867 RegCloseKey(xhkey);
868
869 /* We have the CLSid we want back from the registry as a string, so
870 lets convert it into a CLSID structure */
871 if ( (CLSIDFromString16(buf2,pclsid)) != NOERROR)
872 {
873 return E_INVALIDARG;
874 }
875
876 TRACE ("() Returning CLSID=%s\n", debugstr_guid(pclsid));
877 return (S_OK);
878}
879
880
881
882/***********************************************************************
883 * WriteClassStm
884 *
885 * This function write a CLSID on stream
886 */
887HRESULT WINAPI WriteClassStm(IStream *pStm,REFCLSID rclsid)
888{
889 TRACE("(%p,%p)\n",pStm,rclsid);
890
891 if (rclsid==NULL)
892 return E_INVALIDARG;
893
894 return IStream_Write(pStm,rclsid,sizeof(CLSID),NULL);
895}
896
897/***********************************************************************
898 * ReadClassStm
899 *
900 * This function read a CLSID from a stream
901 */
902HRESULT WINAPI ReadClassStm(IStream *pStm,REFCLSID rclsid)
903{
904 ULONG nbByte;
905 HRESULT res;
906
907 TRACE("(%p,%p)\n",pStm,rclsid);
908
909 if (rclsid==NULL)
910 return E_INVALIDARG;
911
912 res = IStream_Read(pStm,(void*)rclsid,sizeof(CLSID),&nbByte);
913
914 if (FAILED(res))
915 return res;
916
917 if (nbByte != sizeof(CLSID))
918 return S_FALSE;
919 else
920 return S_OK;
921}
922
923#ifndef __WIN32OS2__
924/* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
925/***********************************************************************
926 * LookupETask (COMPOBJ.94)
927 */
928HRESULT WINAPI LookupETask16(HTASK16 *hTask,LPVOID p) {
929 FIXME("(%p,%p),stub!\n",hTask,p);
930 if ((*hTask = GetCurrentTask()) == hETask) {
931 memcpy(p, Table_ETask, sizeof(Table_ETask));
932 }
933 return 0;
934}
935
936/* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
937/***********************************************************************
938 * SetETask (COMPOBJ.95)
939 */
940HRESULT WINAPI SetETask16(HTASK16 hTask, LPVOID p) {
941 FIXME("(%04x,%p),stub!\n",hTask,p);
942 hETask = hTask;
943 return 0;
944}
945
946/* FIXME: this function is not declared in the WINELIB headers. But where should it go ? */
947/***********************************************************************
948 * CallObjectInWOW (COMPOBJ.201)
949 */
950HRESULT WINAPI CallObjectInWOW(LPVOID p1,LPVOID p2) {
951 FIXME("(%p,%p),stub!\n",p1,p2);
952 return 0;
953}
954
955/******************************************************************************
956 * CoRegisterClassObject16 [COMPOBJ.5]
957 *
958 * Don't know where it registers it ...
959 */
960HRESULT WINAPI CoRegisterClassObject16(
961 REFCLSID rclsid,
962 LPUNKNOWN pUnk,
963 DWORD dwClsContext, /* [in] CLSCTX flags indicating the context in which to run the executable */
964 DWORD flags, /* [in] REGCLS flags indicating how connections are made */
965 LPDWORD lpdwRegister
966) {
967 char buf[80];
968
969 WINE_StringFromCLSID(rclsid,buf);
970
971 FIXME("(%s,%p,0x%08lx,0x%08lx,%p),stub\n",
972 buf,pUnk,dwClsContext,flags,lpdwRegister
973 );
974 return 0;
975}
976
977
978/******************************************************************************
979 * CoRevokeClassObject16 [COMPOBJ.6]
980 *
981 */
982HRESULT WINAPI CoRevokeClassObject16(DWORD dwRegister) /* [in] token on class obj */
983{
984 FIXME("(0x%08lx),stub!\n", dwRegister);
985 return 0;
986}
987#endif
988
989
990/***
991 * COM_GetRegisteredClassObject
992 *
993 * This internal method is used to scan the registered class list to
994 * find a class object.
995 *
996 * Params:
997 * rclsid Class ID of the class to find.
998 * dwClsContext Class context to match.
999 * ppv [out] returns a pointer to the class object. Complying
1000 * to normal COM usage, this method will increase the
1001 * reference count on this object.
1002 */
1003static HRESULT COM_GetRegisteredClassObject(
1004 REFCLSID rclsid,
1005 DWORD dwClsContext,
1006 LPUNKNOWN* ppUnk)
1007{
1008 RegisteredClass* curClass;
1009
1010 /*
1011 * Sanity check
1012 */
1013 assert(ppUnk!=0);
1014
1015 /*
1016 * Iterate through the whole list and try to match the class ID.
1017 */
1018 curClass = firstRegisteredClass;
1019
1020 while (curClass != 0)
1021 {
1022 /*
1023 * Check if we have a match on the class ID.
1024 */
1025 if (IsEqualGUID(&(curClass->classIdentifier), rclsid))
1026 {
1027 /*
1028 * Since we don't do out-of process or DCOM just right away, let's ignore the
1029 * class context.
1030 */
1031
1032 /*
1033 * We have a match, return the pointer to the class object.
1034 */
1035 *ppUnk = curClass->classObject;
1036
1037 IUnknown_AddRef(curClass->classObject);
1038
1039 return S_OK;
1040 }
1041
1042 /*
1043 * Step to the next class in the list.
1044 */
1045 curClass = curClass->nextClass;
1046 }
1047
1048 /*
1049 * If we get to here, we haven't found our class.
1050 */
1051 return S_FALSE;
1052}
1053
1054/******************************************************************************
1055 * CoRegisterClassObject [OLE32.36]
1056 *
1057 * This method will register the class object for a given class ID.
1058 *
1059 * See the Windows documentation for more details.
1060 */
1061HRESULT WINAPI CoRegisterClassObject(
1062 REFCLSID rclsid,
1063 LPUNKNOWN pUnk,
1064 DWORD dwClsContext, /* [in] CLSCTX flags indicating the context in which to run the executable */
1065 DWORD flags, /* [in] REGCLS flags indicating how connections are made */
1066 LPDWORD lpdwRegister
1067)
1068{
1069 RegisteredClass* newClass;
1070 LPUNKNOWN foundObject;
1071 HRESULT hr;
1072 char buf[80];
1073
1074 WINE_StringFromCLSID(rclsid,buf);
1075
1076 TRACE("(%s,%p,0x%08lx,0x%08lx,%p)\n",
1077 buf,pUnk,dwClsContext,flags,lpdwRegister);
1078
1079 /*
1080 * Perform a sanity check on the parameters
1081 */
1082 if ( (lpdwRegister==0) || (pUnk==0) )
1083 {
1084 return E_INVALIDARG;
1085}
1086
1087 /*
1088 * Initialize the cookie (out parameter)
1089 */
1090 *lpdwRegister = 0;
1091
1092 /*
1093 * First, check if the class is already registered.
1094 * If it is, this should cause an error.
1095 */
1096 hr = COM_GetRegisteredClassObject(rclsid, dwClsContext, &foundObject);
1097
1098 if (hr == S_OK)
1099 {
1100 /*
1101 * The COM_GetRegisteredClassObject increased the reference count on the
1102 * object so it has to be released.
1103 */
1104 IUnknown_Release(foundObject);
1105
1106 return CO_E_OBJISREG;
1107 }
1108
1109 /*
1110 * If it is not registered, we must create a new entry for this class and
1111 * append it to the registered class list.
1112 * We use the address of the chain node as the cookie since we are sure it's
1113 * unique.
1114 */
1115 newClass = HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass));
1116
1117 /*
1118 * Initialize the node.
1119 */
1120 newClass->classIdentifier = *rclsid;
1121 newClass->runContext = dwClsContext;
1122 newClass->connectFlags = flags;
1123 newClass->dwCookie = (DWORD)newClass;
1124 newClass->nextClass = firstRegisteredClass;
1125
1126 /*
1127 * Since we're making a copy of the object pointer, we have to increase its
1128 * reference count.
1129 */
1130 newClass->classObject = pUnk;
1131 IUnknown_AddRef(newClass->classObject);
1132
1133 firstRegisteredClass = newClass;
1134
1135 /*
1136 * Assign the out parameter (cookie)
1137 */
1138 *lpdwRegister = newClass->dwCookie;
1139
1140 /*
1141 * We're successful Yippee!
1142 */
1143 return S_OK;
1144}
1145
1146/***********************************************************************
1147 * CoRevokeClassObject [OLE32.40]
1148 *
1149 * This method will remove a class object from the class registry
1150 *
1151 * See the Windows documentation for more details.
1152 */
1153HRESULT WINAPI CoRevokeClassObject(
1154 DWORD dwRegister)
1155{
1156 RegisteredClass** prevClassLink;
1157 RegisteredClass* curClass;
1158
1159 TRACE("(%08lx)\n",dwRegister);
1160
1161 /*
1162 * Iterate through the whole list and try to match the cookie.
1163 */
1164 curClass = firstRegisteredClass;
1165 prevClassLink = &firstRegisteredClass;
1166
1167 while (curClass != 0)
1168 {
1169 /*
1170 * Check if we have a match on the cookie.
1171 */
1172 if (curClass->dwCookie == dwRegister)
1173 {
1174 /*
1175 * Remove the class from the chain.
1176 */
1177 *prevClassLink = curClass->nextClass;
1178
1179 /*
1180 * Release the reference to the class object.
1181 */
1182 IUnknown_Release(curClass->classObject);
1183
1184 /*
1185 * Free the memory used by the chain node.
1186 */
1187 HeapFree(GetProcessHeap(), 0, curClass);
1188
1189 return S_OK;
1190}
1191
1192 /*
1193 * Step to the next class in the list.
1194 */
1195 prevClassLink = &(curClass->nextClass);
1196 curClass = curClass->nextClass;
1197 }
1198
1199 /*
1200 * If we get to here, we haven't found our class.
1201 */
1202 return E_INVALIDARG;
1203}
1204
1205/***********************************************************************
1206 * CoGetClassObject [COMPOBJ.7]
1207 */
1208HRESULT WINAPI CoGetClassObject(
1209 REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo,
1210 REFIID iid, LPVOID *ppv
1211) {
1212 LPUNKNOWN regClassObject;
1213 HRESULT hres = E_UNEXPECTED;
1214 char xclsid[80];
1215 WCHAR dllName[MAX_PATH+1];
1216 DWORD dllNameLen = sizeof(dllName);
1217 HINSTANCE hLibrary;
1218#ifdef __WIN32OS2__
1219 typedef HRESULT (* CALLBACK DllGetClassObjectFunc)(REFCLSID clsid,
1220 REFIID iid, LPVOID *ppv);
1221#else
1222 typedef HRESULT CALLBACK (*DllGetClassObjectFunc)(REFCLSID clsid,
1223 REFIID iid, LPVOID *ppv);
1224#endif
1225 DllGetClassObjectFunc DllGetClassObject;
1226
1227 WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
1228
1229 TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",
1230 debugstr_guid(rclsid),
1231 debugstr_guid(iid)
1232 );
1233
1234 if (pServerInfo) {
1235 FIXME("\tpServerInfo: name=%s\n",debugstr_w(pServerInfo->pwszName));
1236 FIXME("\t\tpAuthInfo=%p\n",pServerInfo->pAuthInfo);
1237 }
1238
1239 /*
1240 * First, try and see if we can't match the class ID with one of the
1241 * registered classes.
1242 */
1243 if (S_OK == COM_GetRegisteredClassObject(rclsid, dwClsContext, &regClassObject))
1244 {
1245 /*
1246 * Get the required interface from the retrieved pointer.
1247 */
1248 hres = IUnknown_QueryInterface(regClassObject, iid, ppv);
1249
1250 /*
1251 * Since QI got another reference on the pointer, we want to release the
1252 * one we already have. If QI was unsuccessful, this will release the object. This
1253 * is good since we are not returning it in the "out" parameter.
1254 */
1255 IUnknown_Release(regClassObject);
1256
1257 return hres;
1258 }
1259
1260 /* out of process and remote servers not supported yet */
1261 if ( ((CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER) & dwClsContext)
1262 && !((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext)
1263 ){
1264 FIXME("%s %s not supported!\n",
1265 (dwClsContext&CLSCTX_LOCAL_SERVER)?"CLSCTX_LOCAL_SERVER":"",
1266 (dwClsContext&CLSCTX_REMOTE_SERVER)?"CLSCTX_REMOTE_SERVER":""
1267 );
1268 return E_ACCESSDENIED;
1269 }
1270
1271 if ((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext) {
1272 HKEY key;
1273 char buf[200];
1274
1275 sprintf(buf,"CLSID\\%s\\InprocServer32",xclsid);
1276 hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key);
1277
1278 if (hres != ERROR_SUCCESS) {
1279 return REGDB_E_CLASSNOTREG;
1280 }
1281
1282 memset(dllName,0,sizeof(dllName));
1283 hres= RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)dllName,&dllNameLen);
1284 if (hres)
1285 return REGDB_E_CLASSNOTREG; /* FIXME: check retval */
1286 RegCloseKey(key);
1287 TRACE("found InprocServer32 dll %s\n", debugstr_w(dllName));
1288
1289 /* open dll, call DllGetClassObject */
1290 hLibrary = CoLoadLibrary(dllName, TRUE);
1291 if (hLibrary == 0) {
1292 FIXME("couldn't load InprocServer32 dll %s\n", debugstr_w(dllName));
1293 return E_ACCESSDENIED; /* or should this be CO_E_DLLNOTFOUND? */
1294 }
1295 DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject");
1296 if (!DllGetClassObject) {
1297 /* not sure if this should be called here CoFreeLibrary(hLibrary);*/
1298 FIXME("couldn't find function DllGetClassObject in %s\n", debugstr_w(dllName));
1299 return E_ACCESSDENIED;
1300 }
1301
1302 /*
1303 * Ask the DLL for its class object. (there was a note here about class
1304 * factories but this is good.
1305 */
1306 return DllGetClassObject(rclsid, iid, ppv);
1307 }
1308 return hres;
1309}
1310
1311/***********************************************************************
1312 * CoResumeClassObjects
1313 *
1314 * Resumes classobjects registered with REGCLS suspended
1315 */
1316HRESULT WINAPI CoResumeClassObjects(void)
1317{
1318 FIXME("\n");
1319 return S_OK;
1320}
1321
1322/***********************************************************************
1323 * GetClassFile
1324 *
1325 * This function supplies the CLSID associated with the given filename.
1326 */
1327HRESULT WINAPI GetClassFile(LPOLESTR filePathName,CLSID *pclsid)
1328{
1329 IStorage *pstg=0;
1330 HRESULT res;
1331 int nbElm=0,length=0,i=0;
1332 LONG sizeProgId=20;
1333 LPOLESTR *pathDec=0,absFile=0,progId=0;
1334 WCHAR extention[100]={0};
1335
1336 TRACE("()\n");
1337
1338 /* if the file contain a storage object the return the CLSID writen by IStorage_SetClass method*/
1339 if((StgIsStorageFile(filePathName))==S_OK){
1340
1341 res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
1342
1343 if (SUCCEEDED(res))
1344 res=ReadClassStg(pstg,pclsid);
1345
1346 IStorage_Release(pstg);
1347
1348 return res;
1349 }
1350 /* if the file is not a storage object then attemps to match various bits in the file against a
1351 pattern in the registry. this case is not frequently used ! so I present only the psodocode for
1352 this case
1353
1354 for(i=0;i<nFileTypes;i++)
1355
1356 for(i=0;j<nPatternsForType;j++){
1357
1358 PATTERN pat;
1359 HANDLE hFile;
1360
1361 pat=ReadPatternFromRegistry(i,j);
1362 hFile=CreateFileW(filePathName,,,,,,hFile);
1363 SetFilePosition(hFile,pat.offset);
1364 ReadFile(hFile,buf,pat.size,NULL,NULL);
1365 if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
1366
1367 *pclsid=ReadCLSIDFromRegistry(i);
1368 return S_OK;
1369 }
1370 }
1371 */
1372
1373 /* if the obove strategies fail then search for the extension key in the registry */
1374
1375 /* get the last element (absolute file) in the path name */
1376 nbElm=FileMonikerImpl_DecomposePath(filePathName,&pathDec);
1377 absFile=pathDec[nbElm-1];
1378
1379 /* failed if the path represente a directory and not an absolute file name*/
1380 if (lstrcmpW(absFile,(LPOLESTR)"\\"))
1381 return MK_E_INVALIDEXTENSION;
1382
1383 /* get the extension of the file */
1384 length=lstrlenW(absFile);
1385 for(i=length-1; ( (i>=0) && (extention[i]=absFile[i]) );i--);
1386
1387 /* get the progId associated to the extension */
1388 progId=CoTaskMemAlloc(sizeProgId);
1389
1390 res=RegQueryValueW(HKEY_CLASSES_ROOT,extention,progId,&sizeProgId);
1391
1392 if (res==ERROR_MORE_DATA){
1393
1394 progId = CoTaskMemRealloc(progId,sizeProgId);
1395 res=RegQueryValueW(HKEY_CLASSES_ROOT,extention,progId,&sizeProgId);
1396 }
1397 if (res==ERROR_SUCCESS)
1398 /* return the clsid associated to the progId */
1399 res= CLSIDFromProgID(progId,pclsid);
1400
1401 for(i=0; pathDec[i]!=NULL;i++)
1402 CoTaskMemFree(pathDec[i]);
1403 CoTaskMemFree(pathDec);
1404
1405 CoTaskMemFree(progId);
1406
1407 if (res==ERROR_SUCCESS)
1408 return res;
1409
1410 return MK_E_INVALIDEXTENSION;
1411}
1412#ifndef __WIN32OS2__
1413/******************************************************************************
1414 * CoRegisterMessageFilter16 [COMPOBJ.27]
1415 */
1416HRESULT WINAPI CoRegisterMessageFilter16(
1417 LPMESSAGEFILTER lpMessageFilter,
1418 LPMESSAGEFILTER *lplpMessageFilter
1419) {
1420 FIXME("(%p,%p),stub!\n",lpMessageFilter,lplpMessageFilter);
1421 return 0;
1422}
1423#endif
1424
1425/***********************************************************************
1426 * CoCreateInstance [COMPOBJ.13, OLE32.7]
1427 */
1428HRESULT WINAPI CoCreateInstance(
1429 REFCLSID rclsid,
1430 LPUNKNOWN pUnkOuter,
1431 DWORD dwClsContext,
1432 REFIID iid,
1433 LPVOID *ppv)
1434{
1435 HRESULT hres;
1436 LPCLASSFACTORY lpclf = 0;
1437
1438 /*
1439 * Sanity check
1440 */
1441 if (ppv==0)
1442 return E_POINTER;
1443
1444 /*
1445 * Initialize the "out" parameter
1446 */
1447 *ppv = 0;
1448
1449 /*
1450 * Get a class factory to construct the object we want.
1451 */
1452 hres = CoGetClassObject(rclsid,
1453 dwClsContext,
1454 NULL,
1455 &IID_IClassFactory,
1456 (LPVOID)&lpclf);
1457
1458 if (FAILED(hres)) {
1459 FIXME("no instance created for %s, hres is 0x%08lx\n",debugstr_guid(iid),hres);
1460 return hres;
1461 }
1462
1463 /*
1464 * Create the object and don't forget to release the factory
1465 */
1466 hres = IClassFactory_CreateInstance(lpclf, pUnkOuter, iid, ppv);
1467 IClassFactory_Release(lpclf);
1468
1469 return hres;
1470}
1471
1472/***********************************************************************
1473 * CoCreateInstanceEx [OLE32.165]
1474 */
1475HRESULT WINAPI CoCreateInstanceEx(
1476 REFCLSID rclsid,
1477 LPUNKNOWN pUnkOuter,
1478 DWORD dwClsContext,
1479 COSERVERINFO* pServerInfo,
1480 ULONG cmq,
1481 MULTI_QI* pResults)
1482{
1483 IUnknown* pUnk = NULL;
1484 HRESULT hr;
1485 ULONG index;
1486 int successCount = 0;
1487
1488 /*
1489 * Sanity check
1490 */
1491 if ( (cmq==0) || (pResults==NULL))
1492 return E_INVALIDARG;
1493
1494 if (pServerInfo!=NULL)
1495 FIXME("() non-NULL pServerInfo not supported!\n");
1496
1497 /*
1498 * Initialize all the "out" parameters.
1499 */
1500 for (index = 0; index < cmq; index++)
1501 {
1502 pResults[index].pItf = NULL;
1503 pResults[index].hr = E_NOINTERFACE;
1504 }
1505
1506 /*
1507 * Get the object and get its IUnknown pointer.
1508 */
1509 hr = CoCreateInstance(rclsid,
1510 pUnkOuter,
1511 dwClsContext,
1512 &IID_IUnknown,
1513 (VOID**)&pUnk);
1514
1515 if (hr)
1516 return hr;
1517
1518 /*
1519 * Then, query for all the interfaces requested.
1520 */
1521 for (index = 0; index < cmq; index++)
1522 {
1523 pResults[index].hr = IUnknown_QueryInterface(pUnk,
1524 pResults[index].pIID,
1525 (VOID**)&(pResults[index].pItf));
1526
1527 if (pResults[index].hr == S_OK)
1528 successCount++;
1529 }
1530
1531 /*
1532 * Release our temporary unknown pointer.
1533 */
1534 IUnknown_Release(pUnk);
1535
1536 if (successCount == 0)
1537 return E_NOINTERFACE;
1538
1539 if (successCount!=cmq)
1540 return CO_S_NOTALLINTERFACES;
1541
1542 return S_OK;
1543}
1544
1545/***********************************************************************
1546 * CoFreeLibrary [COMPOBJ.13]
1547 */
1548void WINAPI CoFreeLibrary(HINSTANCE hLibrary)
1549{
1550 OpenDll *ptr, *prev;
1551 OpenDll *tmp;
1552
1553 /* lookup library in linked list */
1554 prev = NULL;
1555 for (ptr = openDllList; ptr != NULL; ptr=ptr->next) {
1556 if (ptr->hLibrary == hLibrary) {
1557 break;
1558 }
1559 prev = ptr;
1560 }
1561
1562 if (ptr == NULL) {
1563 /* shouldn't happen if user passed in a valid hLibrary */
1564 return;
1565 }
1566 /* assert: ptr points to the library entry to free */
1567
1568 /* free library and remove node from list */
1569 FreeLibrary(hLibrary);
1570 if (ptr == openDllList) {
1571 tmp = openDllList->next;
1572 HeapFree(GetProcessHeap(), 0, openDllList);
1573 openDllList = tmp;
1574 } else {
1575 tmp = ptr->next;
1576 HeapFree(GetProcessHeap(), 0, ptr);
1577 prev->next = tmp;
1578 }
1579
1580}
1581
1582
1583/***********************************************************************
1584 * CoFreeAllLibraries [COMPOBJ.12]
1585 */
1586void WINAPI CoFreeAllLibraries(void)
1587{
1588 OpenDll *ptr, *tmp;
1589
1590 for (ptr = openDllList; ptr != NULL; ) {
1591 tmp=ptr->next;
1592 CoFreeLibrary(ptr->hLibrary);
1593 ptr = tmp;
1594 }
1595}
1596
1597
1598
1599/***********************************************************************
1600 * CoFreeUnusedLibraries [COMPOBJ.17]
1601 */
1602void WINAPI CoFreeUnusedLibraries(void)
1603{
1604 OpenDll *ptr, *tmp;
1605 typedef HRESULT(*DllCanUnloadNowFunc)(void);
1606 DllCanUnloadNowFunc DllCanUnloadNow;
1607
1608 for (ptr = openDllList; ptr != NULL; ) {
1609 DllCanUnloadNow = (DllCanUnloadNowFunc)
1610 GetProcAddress(ptr->hLibrary, "DllCanUnloadNow");
1611
1612 if ( (DllCanUnloadNow != NULL) &&
1613 (DllCanUnloadNow() == S_OK) ) {
1614 tmp=ptr->next;
1615 CoFreeLibrary(ptr->hLibrary);
1616 ptr = tmp;
1617 } else {
1618 ptr=ptr->next;
1619 }
1620 }
1621}
1622
1623/***********************************************************************
1624 * CoFileTimeNow [COMPOBJ.82, OLE32.10]
1625 * RETURNS
1626 * the current system time in lpFileTime
1627 */
1628HRESULT WINAPI CoFileTimeNow( FILETIME *lpFileTime ) /* [out] the current time */
1629{
1630 GetSystemTimeAsFileTime( lpFileTime );
1631 return S_OK;
1632}
1633
1634/***********************************************************************
1635 * CoTaskMemAlloc (OLE32.43)
1636 * RETURNS
1637 * pointer to newly allocated block
1638 */
1639LPVOID WINAPI CoTaskMemAlloc(
1640 ULONG size /* [in] size of memoryblock to be allocated */
1641) {
1642 LPMALLOC lpmalloc;
1643 HRESULT ret = CoGetMalloc(0,&lpmalloc);
1644
1645 if (FAILED(ret))
1646 return NULL;
1647
1648 return IMalloc_Alloc(lpmalloc,size);
1649}
1650/***********************************************************************
1651 * CoTaskMemFree (OLE32.44)
1652 */
1653VOID WINAPI CoTaskMemFree(
1654 LPVOID ptr /* [in] pointer to be freed */
1655) {
1656 LPMALLOC lpmalloc;
1657 HRESULT ret = CoGetMalloc(0,&lpmalloc);
1658
1659 if (FAILED(ret))
1660 return;
1661
1662 IMalloc_Free(lpmalloc, ptr);
1663}
1664
1665/***********************************************************************
1666 * CoTaskMemRealloc (OLE32.45)
1667 * RETURNS
1668 * pointer to newly allocated block
1669 */
1670LPVOID WINAPI CoTaskMemRealloc(
1671 LPVOID pvOld,
1672 ULONG size) /* [in] size of memoryblock to be allocated */
1673{
1674 LPMALLOC lpmalloc;
1675 HRESULT ret = CoGetMalloc(0,&lpmalloc);
1676
1677 if (FAILED(ret))
1678 return NULL;
1679
1680 return IMalloc_Realloc(lpmalloc, pvOld, size);
1681}
1682
1683/***********************************************************************
1684 * CoLoadLibrary (OLE32.30)
1685 */
1686HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree)
1687{
1688 HINSTANCE hLibrary;
1689 OpenDll *ptr;
1690 OpenDll *tmp;
1691
1692 TRACE("(%s, %d)\n", debugstr_w(lpszLibName), bAutoFree);
1693
1694 hLibrary = LoadLibraryExW(lpszLibName, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
1695
1696 if (!bAutoFree)
1697 return hLibrary;
1698
1699 if (openDllList == NULL) {
1700 /* empty list -- add first node */
1701 openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
1702 openDllList->hLibrary=hLibrary;
1703 openDllList->next = NULL;
1704 } else {
1705 /* search for this dll */
1706 int found = FALSE;
1707 for (ptr = openDllList; ptr->next != NULL; ptr=ptr->next) {
1708 if (ptr->hLibrary == hLibrary) {
1709 found = TRUE;
1710 break;
1711 }
1712 }
1713 if (!found) {
1714 /* dll not found, add it */
1715 tmp = openDllList;
1716 openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
1717 openDllList->hLibrary = hLibrary;
1718 openDllList->next = tmp;
1719 }
1720 }
1721
1722 return hLibrary;
1723}
1724
1725/***********************************************************************
1726 * CoInitializeWOW (OLE32.27)
1727 */
1728HRESULT WINAPI CoInitializeWOW(DWORD x,DWORD y) {
1729 FIXME("(0x%08lx,0x%08lx),stub!\n",x,y);
1730 return 0;
1731}
1732
1733#ifndef __WIN32OS2__
1734/******************************************************************************
1735 * CoLockObjectExternal16 [COMPOBJ.63]
1736 */
1737HRESULT WINAPI CoLockObjectExternal16(
1738 LPUNKNOWN pUnk, /* [in] object to be locked */
1739 BOOL16 fLock, /* [in] do lock */
1740 BOOL16 fLastUnlockReleases /* [in] ? */
1741) {
1742 FIXME("(%p,%d,%d),stub!\n",pUnk,fLock,fLastUnlockReleases);
1743 return S_OK;
1744}
1745#endif
1746
1747/******************************************************************************
1748 * CoLockObjectExternal [OLE32.31]
1749 */
1750HRESULT WINAPI CoLockObjectExternal(
1751 LPUNKNOWN pUnk, /* [in] object to be locked */
1752 BOOL fLock, /* [in] do lock */
1753 BOOL fLastUnlockReleases) /* [in] unlock all */
1754{
1755
1756 if (fLock)
1757 {
1758 /*
1759 * Increment the external lock coutner, COM_ExternalLockAddRef also
1760 * increment the object's internal lock counter.
1761 */
1762 COM_ExternalLockAddRef( pUnk);
1763 }
1764 else
1765 {
1766 /*
1767 * Decrement the external lock coutner, COM_ExternalLockRelease also
1768 * decrement the object's internal lock counter.
1769 */
1770 COM_ExternalLockRelease( pUnk, fLastUnlockReleases);
1771 }
1772
1773 return S_OK;
1774}
1775
1776#ifndef __WIN32OS2__
1777/***********************************************************************
1778 * CoGetState16 [COMPOBJ.115]
1779 */
1780HRESULT WINAPI CoGetState16(LPDWORD state)
1781{
1782 FIXME("(%p),stub!\n", state);
1783 *state = 0;
1784 return S_OK;
1785}
1786/***********************************************************************
1787 * CoSetState [COM32.42]
1788 */
1789HRESULT WINAPI CoSetState(LPDWORD state)
1790{
1791 FIXME("(%p),stub!\n", state);
1792 if (state) *state = 0;
1793 return S_OK;
1794}
1795#endif
1796/***********************************************************************
1797 * CoCreateFreeThreadedMarshaler [OLE32.5]
1798 */
1799HRESULT WINAPI CoCreateFreeThreadedMarshaler (LPUNKNOWN punkOuter, LPUNKNOWN* ppunkMarshal)
1800{
1801 FIXME ("(%p %p): stub\n", punkOuter, ppunkMarshal);
1802
1803 return S_OK;
1804}
1805
1806
1807/***********************************************************************
1808 * DllGetClassObject [OLE32.63]
1809 */
1810HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
1811{
1812 FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
1813 *ppv = NULL;
1814 return CLASS_E_CLASSNOTAVAILABLE;
1815}
1816
1817
1818/***
1819 * COM_RevokeAllClasses
1820 *
1821 * This method is called when the COM libraries are uninitialized to
1822 * release all the references to the class objects registered with
1823 * the library
1824 */
1825static void COM_RevokeAllClasses()
1826{
1827 while (firstRegisteredClass!=0)
1828 {
1829 CoRevokeClassObject(firstRegisteredClass->dwCookie);
1830 }
1831}
1832
1833/****************************************************************************
1834 * COM External Lock methods implementation
1835 */
1836
1837/****************************************************************************
1838 * Public - Method that increments the count for a IUnknown* in the linked
1839 * list. The item is inserted if not already in the list.
1840 */
1841static void COM_ExternalLockAddRef(
1842 IUnknown *pUnk)
1843{
1844 COM_ExternalLock *externalLock = COM_ExternalLockFind(pUnk);
1845
1846 /*
1847 * Add an external lock to the object. If it was already externally
1848 * locked, just increase the reference count. If it was not.
1849 * add the item to the list.
1850 */
1851 if ( externalLock == EL_NOT_FOUND )
1852 COM_ExternalLockInsert(pUnk);
1853 else
1854 externalLock->uRefCount++;
1855
1856 /*
1857 * Add an internal lock to the object
1858 */
1859 IUnknown_AddRef(pUnk);
1860}
1861
1862/****************************************************************************
1863 * Public - Method that decrements the count for a IUnknown* in the linked
1864 * list. The item is removed from the list if its count end up at zero or if
1865 * bRelAll is TRUE.
1866 */
1867static void COM_ExternalLockRelease(
1868 IUnknown *pUnk,
1869 BOOL bRelAll)
1870{
1871 COM_ExternalLock *externalLock = COM_ExternalLockFind(pUnk);
1872
1873 if ( externalLock != EL_NOT_FOUND )
1874 {
1875 do
1876 {
1877 externalLock->uRefCount--; /* release external locks */
1878 IUnknown_Release(pUnk); /* release local locks as well */
1879
1880 if ( bRelAll == FALSE )
1881 break; /* perform single release */
1882
1883 } while ( externalLock->uRefCount > 0 );
1884
1885 if ( externalLock->uRefCount == 0 ) /* get rid of the list entry */
1886 COM_ExternalLockDelete(externalLock);
1887 }
1888}
1889/****************************************************************************
1890 * Public - Method that frees the content of the list.
1891 */
1892static void COM_ExternalLockFreeList()
1893{
1894 COM_ExternalLock *head;
1895
1896 head = elList.head; /* grab it by the head */
1897 while ( head != EL_END_OF_LIST )
1898 {
1899 COM_ExternalLockDelete(head); /* get rid of the head stuff */
1900
1901 head = elList.head; /* get the new head... */
1902 }
1903}
1904
1905/****************************************************************************
1906 * Public - Method that dump the content of the list.
1907 */
1908void COM_ExternalLockDump()
1909{
1910 COM_ExternalLock *current = elList.head;
1911
1912 DPRINTF("\nExternal lock list contains:\n");
1913
1914 while ( current != EL_END_OF_LIST )
1915 {
1916 DPRINTF( "\t%p with %lu references count.\n", current->pUnk, current->uRefCount);
1917
1918 /* Skip to the next item */
1919 current = current->next;
1920 }
1921
1922}
1923
1924/****************************************************************************
1925 * Internal - Find a IUnknown* in the linked list
1926 */
1927static COM_ExternalLock* COM_ExternalLockFind(
1928 IUnknown *pUnk)
1929{
1930 return COM_ExternalLockLocate(elList.head, pUnk);
1931}
1932
1933/****************************************************************************
1934 * Internal - Recursivity agent for IUnknownExternalLockList_Find
1935 */
1936static COM_ExternalLock* COM_ExternalLockLocate(
1937 COM_ExternalLock *element,
1938 IUnknown *pUnk)
1939{
1940 if ( element == EL_END_OF_LIST )
1941 return EL_NOT_FOUND;
1942
1943 else if ( element->pUnk == pUnk ) /* We found it */
1944 return element;
1945
1946 else /* Not the right guy, keep on looking */
1947 return COM_ExternalLockLocate( element->next, pUnk);
1948}
1949
1950/****************************************************************************
1951 * Internal - Insert a new IUnknown* to the linked list
1952 */
1953static BOOL COM_ExternalLockInsert(
1954 IUnknown *pUnk)
1955{
1956 COM_ExternalLock *newLock = NULL;
1957 COM_ExternalLock *previousHead = NULL;
1958
1959 /*
1960 * Allocate space for the new storage object
1961 */
1962 newLock = HeapAlloc(GetProcessHeap(), 0, sizeof(COM_ExternalLock));
1963
1964 if (newLock!=NULL)
1965 {
1966 if ( elList.head == EL_END_OF_LIST )
1967 {
1968 elList.head = newLock; /* The list is empty */
1969 }
1970 else
1971 {
1972 /*
1973 * insert does it at the head
1974 */
1975 previousHead = elList.head;
1976 elList.head = newLock;
1977 }
1978
1979 /*
1980 * Set new list item data member
1981 */
1982 newLock->pUnk = pUnk;
1983 newLock->uRefCount = 1;
1984 newLock->next = previousHead;
1985
1986 return TRUE;
1987 }
1988 else
1989 return FALSE;
1990}
1991
1992/****************************************************************************
1993 * Internal - Method that removes an item from the linked list.
1994 */
1995static void COM_ExternalLockDelete(
1996 COM_ExternalLock *itemList)
1997{
1998 COM_ExternalLock *current = elList.head;
1999
2000 if ( current == itemList )
2001 {
2002 /*
2003 * this section handles the deletion of the first node
2004 */
2005 elList.head = itemList->next;
2006 HeapFree( GetProcessHeap(), 0, itemList);
2007 }
2008 else
2009 {
2010 do
2011 {
2012 if ( current->next == itemList ) /* We found the item to free */
2013 {
2014 current->next = itemList->next; /* readjust the list pointers */
2015
2016 HeapFree( GetProcessHeap(), 0, itemList);
2017 break;
2018 }
2019
2020 /* Skip to the next item */
2021 current = current->next;
2022
2023 } while ( current != EL_END_OF_LIST );
2024 }
2025}
2026
2027#ifndef __WIN32OS2__
2028/***********************************************************************
2029 * COMPOBJ_DllEntryPoint [COMPOBJ.entry]
2030 *
2031 * Initialization code for the COMPOBJ DLL
2032 *
2033 * RETURNS:
2034 */
2035BOOL WINAPI COMPOBJ_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst, WORD ds, WORD HeapSize, DWORD res1, WORD res2)
2036{
2037 TRACE("(%08lx, %04x, %04x, %04x, %08lx, %04x)\n", Reason, hInst, ds, HeapSize,
2038 res1, res2);
2039 switch(Reason)
2040 {
2041 case DLL_PROCESS_ATTACH:
2042 if (!COMPOBJ_Attach++) COMPOBJ_hInstance = hInst;
2043 break;
2044
2045 case DLL_PROCESS_DETACH:
2046 if(!--COMPOBJ_Attach)
2047 COMPOBJ_hInstance = 0;
2048 break;
2049 }
2050 return TRUE;
2051}
2052#endif
2053/******************************************************************************
2054 * OleGetAutoConvert [OLE32.104]
2055 */
2056HRESULT WINAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew)
2057{
2058 HKEY hkey = 0;
2059 char buf[200];
2060 WCHAR wbuf[200];
2061 DWORD len;
2062 HRESULT res = S_OK;
2063
2064 sprintf(buf,"CLSID\\");WINE_StringFromCLSID(clsidOld,&buf[6]);
2065 if (RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&hkey))
2066 {
2067 res = REGDB_E_CLASSNOTREG;
2068 goto done;
2069 }
2070 len = 200;
2071 /* we can just query for the default value of AutoConvertTo key like that,
2072 without opening the AutoConvertTo key and querying for NULL (default) */
2073 if (RegQueryValueA(hkey,"AutoConvertTo",buf,&len))
2074 {
2075 res = REGDB_E_KEYMISSING;
2076 goto done;
2077 }
2078 MultiByteToWideChar( CP_ACP, 0, buf, -1, wbuf, sizeof(wbuf)/sizeof(WCHAR) );
2079 CLSIDFromString(wbuf,pClsidNew);
2080done:
2081 if (hkey) RegCloseKey(hkey);
2082
2083 return res;
2084}
2085
2086/******************************************************************************
2087 * OleSetAutoConvert [OLE32.126]
2088 */
2089HRESULT WINAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew)
2090{
2091 HKEY hkey = 0, hkeyConvert = 0;
2092 char buf[200], szClsidNew[200];
2093 HRESULT res = S_OK;
2094
2095 TRACE("(%p,%p);\n", clsidOld, clsidNew);
2096 sprintf(buf,"CLSID\\");WINE_StringFromCLSID(clsidOld,&buf[6]);
2097 WINE_StringFromCLSID(clsidNew, szClsidNew);
2098 if (RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&hkey))
2099 {
2100 res = REGDB_E_CLASSNOTREG;
2101 goto done;
2102 }
2103 if (RegCreateKeyA(hkey, "AutoConvertTo", &hkeyConvert))
2104 {
2105 res = REGDB_E_WRITEREGDB;
2106 goto done;
2107 }
2108 if (RegSetValueExA(hkeyConvert, NULL, 0,
2109 REG_SZ, (LPBYTE)szClsidNew, strlen(szClsidNew)+1))
2110 {
2111 res = REGDB_E_WRITEREGDB;
2112 goto done;
2113 }
2114
2115done:
2116 if (hkeyConvert) RegCloseKey(hkeyConvert);
2117 if (hkey) RegCloseKey(hkey);
2118
2119 return res;
2120}
2121
2122/***********************************************************************
2123 * IsEqualGUID [OLE32.76]
2124 *
2125 * Compares two Unique Identifiers.
2126 *
2127 * RETURNS
2128 * TRUE if equal
2129 */
2130#undef IsEqualGUID
2131BOOL WINAPI IsEqualGUID(
2132 REFGUID rguid1, /* [in] unique id 1 */
2133 REFGUID rguid2 /* [in] unique id 2 */
2134 )
2135{
2136 return !memcmp(rguid1,rguid2,sizeof(GUID));
2137}
2138
2139#ifdef __WIN32OS2__
2140// ----------------------------------------------------------------------
2141// CLSIDFromStringA()
2142// @@@PH: this is not a WINE API, but a replacement for CLSIDFromString16
2143// which used to accept ASCII strings instead of OLE strings
2144// ----------------------------------------------------------------------
2145
2146HRESULT WIN32API CLSIDFromStringA(
2147 LPCSTR lpsz, // [in] - ASCII string CLSID
2148 LPCLSID pclsid) // [out] - Binary CLSID
2149{
2150 return CLSIDFromString16(lpsz, pclsid);
2151}
2152#endif
Note: See TracBrowser for help on using the repository browser.