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

Last change on this file since 6666 was 6648, checked in by bird, 24 years ago

Added $Id:$ keyword.

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