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

Last change on this file since 7508 was 7508, checked in by sandervl, 24 years ago

removed TRACE/WARN macro redefinition

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